<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>案例研究 on Tarragon</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/</link><description>Recent content in 案例研究 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Wed, 21 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/index.xml" rel="self" type="application/rss+xml"/><item><title>案例：Cython 加速 Markdown 解析</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/</guid><description>&lt;p>本案例基於 &lt;code>.claude/lib/markdown_link_checker.py&lt;/code> 的實際程式碼，展示如何用 Cython 加速文字解析。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">4.2 Cython：Python 語法的 C 速度&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="現有設計">現有設計&lt;/h3>
&lt;p>&lt;code>markdown_link_checker.py&lt;/code> 使用純 Python 解析 Markdown 連結。讓我們看看核心程式碼：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MarkdownLinkChecker&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Markdown 連結檢查器&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Markdown 連結正則表達式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 匹配 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target) 格式，排除圖片 ![alt](/python-advanced/05-c-extensions/case-studies/cython-markdown/src)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">INLINE_LINK_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;(?&amp;lt;!!)\[([^\]]+)\]\(([^)]+)\)&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結定義 [ref]: target&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">REFERENCE_DEF_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;^\s*\[([^\]]+)\]:\s*(.+)$&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">MULTILINE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結使用 [text][ref]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="n">REFERENCE_USE_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;\[([^\]]+)\]\[([^\]]+)\]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">parse_markdown_links&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">Dict&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="s2"> 解析 Markdown 內容中的所有連結
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="s2"> content: Markdown 內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="s2"> list[dict]: 連結列表，每個包含 text, target, line
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">lines&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 首先收集引用式連結定義&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="n">reference_defs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">REFERENCE_DEF_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ref_name&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ref_target&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 追蹤是否在程式碼區塊內&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="n">in_code_block&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 解析行內連結&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">line_num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">line&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">enumerate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lines&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 檢查程式碼區塊開始/結束&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">line&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">startswith&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;```&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="n">in_code_block&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">in_code_block&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 跳過程式碼區塊內的連結&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">in_code_block&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 行內連結 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">INLINE_LINK_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;target&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;line&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">line_num&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">65&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">66&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結 [text][ref]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">67&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">REFERENCE_USE_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">68&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">69&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ref_name&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">70&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">71&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">72&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;target&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ref_name&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">73&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;line&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">line_num&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">74&lt;/span>&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">75&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">76&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">links&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="效能限制">效能限制&lt;/h3>
&lt;p>純 Python 的限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>正則表達式呼叫開銷&lt;/strong>：每次 &lt;code>finditer()&lt;/code> 都有 Python 層級的迭代器開銷&lt;/li>
&lt;li>&lt;strong>迴圈效率不如 C&lt;/strong>：Python 的 for 迴圈涉及迭代器協議和物件建立&lt;/li>
&lt;li>&lt;strong>字串處理有額外開銷&lt;/strong>：&lt;code>split()&lt;/code>、&lt;code>strip()&lt;/code>、&lt;code>startswith()&lt;/code> 都會建立新物件&lt;/li>
&lt;li>&lt;strong>字典存取開銷&lt;/strong>：&lt;code>reference_defs[ref_name]&lt;/code> 涉及雜湊計算和物件比較&lt;/li>
&lt;/ul>
&lt;p>當處理大量 Markdown 文件（例如整個文件專案）時，這些開銷會累積成可觀的效能損失。&lt;/p>
&lt;h2 id="進階解決方案">進階解決方案&lt;/h2>
&lt;h3 id="優化目標">優化目標&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>保持相同的 API&lt;/strong>：不改變 &lt;code>parse_markdown_links()&lt;/code> 的輸入輸出格式&lt;/li>
&lt;li>&lt;strong>顯著提升解析速度&lt;/strong>：目標 2-5x 加速&lt;/li>
&lt;li>&lt;strong>容易整合到現有專案&lt;/strong>：編譯後可直接替換原模組&lt;/li>
&lt;/ol>
&lt;h3 id="實作步驟">實作步驟&lt;/h3>
&lt;h4 id="步驟-1建立-pyx-檔案">步驟 1：建立 .pyx 檔案&lt;/h4>
&lt;p>首先，建立基本的 Cython 檔案結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cython" data-lang="cython">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c"># markdown_parser.pyx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="sd">Cython accelerated Markdown link parser.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="sd">This module provides fast parsing of Markdown links,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="sd">compatible with the original Python implementation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="k">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="k">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="k">import&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c"># Compile regex patterns at module level for reuse&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">INLINE_LINK_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;(?&amp;lt;!!)\[([^\]]+)\]\(([^)]+)\)&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">REFERENCE_DEF_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;^\s*\[([^\]]+)\]:\s*(.+)$&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">MULTILINE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">REFERENCE_USE_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;\[([^\]]+)\]\[([^\]]+)\]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>重點說明&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>本案例基於 <code>.claude/lib/markdown_link_checker.py</code> 的實際程式碼，展示如何用 Cython 加速文字解析。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">4.2 Cython：Python 語法的 C 速度</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="現有設計">現有設計</h3>
<p><code>markdown_link_checker.py</code> 使用純 Python 解析 Markdown 連結。讓我們看看核心程式碼：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">class</span> <span class="nc">MarkdownLinkChecker</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Markdown 連結檢查器&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="c1"># Markdown 連結正則表達式</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1"># 匹配 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target) 格式，排除圖片 ![alt](/python-advanced/05-c-extensions/case-studies/cython-markdown/src)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># 引用式連結定義 [ref]: target</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1"># 引用式連結使用 [text][ref]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">def</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">        解析 Markdown 內容中的所有連結
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">            content: Markdown 內容
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">        Returns:
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="s2">            list[dict]: 連結列表，每個包含 text, target, line
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">        <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c1"># 首先收集引用式連結定義</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">        <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">            <span class="n">ref_target</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">            <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="c1"># 追蹤是否在程式碼區塊內</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">        <span class="n">in_code_block</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">
</span></span><span class="line"><span class="ln">47</span><span class="cl">        <span class="c1"># 解析行內連結</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">        <span class="k">for</span> <span class="n">line_num</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">            <span class="c1"># 檢查程式碼區塊開始/結束</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">            <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">                <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">
</span></span><span class="line"><span class="ln">54</span><span class="cl">            <span class="c1"># 跳過程式碼區塊內的連結</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">            <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">
</span></span><span class="line"><span class="ln">58</span><span class="cl">            <span class="c1"># 行內連結 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">                    <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">                    <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">                    <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="ln">65</span><span class="cl">
</span></span><span class="line"><span class="ln">66</span><span class="cl">            <span class="c1"># 引用式連結 [text][ref]</span>
</span></span><span class="line"><span class="ln">67</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">68</span><span class="cl">                <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">69</span><span class="cl">                <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">70</span><span class="cl">                    <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">71</span><span class="cl">                        <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">72</span><span class="cl">                        <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">73</span><span class="cl">                        <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">74</span><span class="cl">                    <span class="p">})</span>
</span></span><span class="line"><span class="ln">75</span><span class="cl">
</span></span><span class="line"><span class="ln">76</span><span class="cl">        <span class="k">return</span> <span class="n">links</span></span></span></code></pre></div><h3 id="效能限制">效能限制</h3>
<p>純 Python 的限制：</p>
<ul>
<li><strong>正則表達式呼叫開銷</strong>：每次 <code>finditer()</code> 都有 Python 層級的迭代器開銷</li>
<li><strong>迴圈效率不如 C</strong>：Python 的 for 迴圈涉及迭代器協議和物件建立</li>
<li><strong>字串處理有額外開銷</strong>：<code>split()</code>、<code>strip()</code>、<code>startswith()</code> 都會建立新物件</li>
<li><strong>字典存取開銷</strong>：<code>reference_defs[ref_name]</code> 涉及雜湊計算和物件比較</li>
</ul>
<p>當處理大量 Markdown 文件（例如整個文件專案）時，這些開銷會累積成可觀的效能損失。</p>
<h2 id="進階解決方案">進階解決方案</h2>
<h3 id="優化目標">優化目標</h3>
<ol>
<li><strong>保持相同的 API</strong>：不改變 <code>parse_markdown_links()</code> 的輸入輸出格式</li>
<li><strong>顯著提升解析速度</strong>：目標 2-5x 加速</li>
<li><strong>容易整合到現有專案</strong>：編譯後可直接替換原模組</li>
</ol>
<h3 id="實作步驟">實作步驟</h3>
<h4 id="步驟-1建立-pyx-檔案">步驟 1：建立 .pyx 檔案</h4>
<p>首先，建立基本的 Cython 檔案結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="sd">Cython accelerated Markdown link parser.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">This module provides fast parsing of Markdown links,
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">compatible with the original Python implementation.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">from</span> <span class="nn">typing</span> <span class="k">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c"># Compile regex patterns at module level for reuse</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s">r&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="s">r&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="s">r&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li>使用 <code>cdef object</code> 宣告正則表達式物件，讓 Cython 知道這些是 Python 物件</li>
<li>將正則表達式編譯放在模組層級，避免重複編譯</li>
<li>保留 docstring 和 type hints 以維護可讀性</li>
</ul>
<h4 id="步驟-2添加型別宣告">步驟 2：添加型別宣告</h4>
<p>為關鍵變數添加 C 型別宣告：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">LinkInfo</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    C-level struct to hold link information.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">    Faster than Python dict for internal operations.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">text</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">target</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">int</span> <span class="nf">line</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">str</span> <span class="n">text</span><span class="p">,</span> <span class="nb">str</span> <span class="n">target</span><span class="p">,</span> <span class="nb">int</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">line</span> <span class="o">=</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">def</span> <span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="sd">&#34;&#34;&#34;Convert to dictionary for API compatibility.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="s">&#34;text&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="s">&#34;target&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="s">&#34;line&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">line</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">cdef</span> <span class="kt">bint</span> <span class="nf">is_code_fence</span><span class="p">(</span><span class="nb">str</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="sd">    Check if line is a code fence marker.
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="sd">    cdef function: only callable from Cython, fastest.
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">cdef</span> <span class="kt">str</span> <span class="nf">stripped</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;```&#34;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;~~~&#34;</span><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cdef class LinkInfo</code>：使用 Cython 的擴展類別，內部存取比 Python dict 快</li>
<li><code>cdef public</code>：讓屬性可以從 Python 存取，同時保持 C 層級效率</li>
<li><code>cdef bint</code>：使用 C 的布林型別（0 或 1），比 Python 的 <code>bool</code> 快</li>
<li><code>cdef</code> 函式：只能從 Cython 呼叫，沒有 Python 呼叫開銷</li>
</ul>
<h4 id="步驟-3優化迴圈">步驟 3：優化迴圈</h4>
<p>使用 Cython 優化主要的解析迴圈：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="kt">list</span> <span class="nf">_parse_inline_links</span><span class="p">(</span><span class="nb">list</span> <span class="n">lines</span><span class="p">,</span> <span class="nb">dict</span> <span class="n">reference_defs</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    Parse inline and reference links from lines.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    Internal function with optimized loop.
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="nb">list</span> <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="nb">int</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="nb">int</span> <span class="n">total_lines</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">bint</span> <span class="n">in_code_block</span> <span class="o">=</span> <span class="bp">False</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="nb">str</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">for</span> <span class="n">line_num</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">total_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">line</span> <span class="o">=</span> <span class="n">lines</span><span class="p">[</span><span class="n">line_num</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="c"># Check code fence</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">if</span> <span class="n">is_code_fence</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="c"># Parse inline links [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">                <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>  <span class="c"># 1-indexed</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">            <span class="p">))</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c"># Parse reference links [text][ref]</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">            <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">                    <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">                    <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">                    <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">                <span class="p">))</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">
</span></span><span class="line"><span class="ln">47</span><span class="cl">    <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">
</span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="k">cdef</span> <span class="kt">dict</span> <span class="nf">_collect_reference_defs</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="sd">    Collect reference link definitions from content.
</span></span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="sd">    Returns dict mapping ref_name -&gt; target.
</span></span></span><span class="line"><span class="ln">54</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">
</span></span><span class="line"><span class="ln">61</span><span class="cl">    <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">        <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">        <span class="n">ref_target</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">        <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">65</span><span class="cl">
</span></span><span class="line"><span class="ln">66</span><span class="cl">    <span class="k">return</span> <span class="n">reference_defs</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cdef list</code>、<code>cdef dict</code>：明確宣告容器型別，減少型別檢查開銷</li>
<li><code>cdef int line_num</code>：使用 C 整數進行迴圈計數</li>
<li><code>cdef bint in_code_block</code>：使用 C 布林型別追蹤狀態</li>
<li>將功能分解成多個 <code>cdef</code> 函式，每個函式專注單一職責</li>
</ul>
<h4 id="步驟-4建立公開-api">步驟 4：建立公開 API</h4>
<p>使用 <code>cpdef</code> 或 <code>def</code> 建立可從 Python 呼叫的公開介面：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cpdef</span> <span class="kt">list</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    Parse all links from Markdown content.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    This is the main public API, compatible with the original
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="sd">    Python implementation.
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="sd">    Args:
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="sd">        content: Markdown content string
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="sd">        List of dicts with &#39;text&#39;, &#39;target&#39;, &#39;line&#39; keys
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="nb">list</span> <span class="n">link_infos</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="nb">list</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">LinkInfo</span> <span class="n">info</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c"># Split content into lines</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="c"># Collect reference definitions</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c"># Parse all links</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">link_infos</span> <span class="o">=</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="c"># Convert to dict format for API compatibility</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">info</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">info</span> <span class="ow">in</span> <span class="n">link_infos</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_py</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="sd">    Python-compatible wrapper with type hints.
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="sd">    Identical to parse_markdown_links but with explicit
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="sd">    Python type annotations for better IDE support.
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="k">return</span> <span class="n">parse_markdown_links</span><span class="p">(</span><span class="n">content</span><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cpdef</code>：同時產生 Python 和 C 版本，從 Python 呼叫時用 Python 版本，從 Cython 呼叫時用 C 版本</li>
<li>保持 API 相容性：回傳格式與原始 Python 版本完全相同</li>
<li>提供 <code>_py</code> 版本：帶有完整型別提示，改善 IDE 支援</li>
</ul>
<h4 id="步驟-5建立-setuppy">步驟 5：建立 setup.py</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">Build script for Cython markdown parser.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">Usage:
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">Or for development with automatic rebuild:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    pip install -e .
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span><span class="p">,</span> <span class="n">Extension</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="kn">from</span> <span class="nn">Cython.Build</span> <span class="kn">import</span> <span class="n">cythonize</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">extensions</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">Extension</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="s2">&#34;markdown_parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">sources</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;markdown_parser.pyx&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="c1"># Optional: add compiler directives for optimization</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="c1"># extra_compile_args=[&#34;-O3&#34;],</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="n">name</span><span class="o">=</span><span class="s2">&#34;markdown_parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">version</span><span class="o">=</span><span class="s2">&#34;0.1.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">description</span><span class="o">=</span><span class="s2">&#34;Cython accelerated Markdown link parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">cythonize</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">extensions</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="n">compiler_directives</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="s2">&#34;language_level&#34;</span><span class="p">:</span> <span class="s2">&#34;3&#34;</span><span class="p">,</span>      <span class="c1"># Python 3 syntax</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">            <span class="s2">&#34;boundscheck&#34;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>       <span class="c1"># Disable bounds checking</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="s2">&#34;wraparound&#34;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>        <span class="c1"># Disable negative indexing</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="s2">&#34;cdivision&#34;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>          <span class="c1"># Use C division semantics</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="n">annotate</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>  <span class="c1"># Generate HTML annotation file</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="n">zip_safe</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>編譯指令說明</strong>：</p>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>說明</th>
          <th>效能影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>language_level=3</code></td>
          <td>使用 Python 3 語法</td>
          <td>無</td>
      </tr>
      <tr>
          <td><code>boundscheck=False</code></td>
          <td>停用陣列邊界檢查</td>
          <td>加速 5-10%</td>
      </tr>
      <tr>
          <td><code>wraparound=False</code></td>
          <td>停用負數索引支援</td>
          <td>加速 2-5%</td>
      </tr>
      <tr>
          <td><code>cdivision=True</code></td>
          <td>使用 C 的除法（不檢查除以零）</td>
          <td>加速除法運算</td>
      </tr>
      <tr>
          <td><code>annotate=True</code></td>
          <td>產生 HTML 註解報告</td>
          <td>僅開發時使用</td>
      </tr>
  </tbody>
</table>
<h3 id="完整程式碼">完整程式碼</h3>
<p>將以上所有部分整合成完整的 <code>.pyx</code> 檔案：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c"># markdown_parser.pyx</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="sd">Cython accelerated Markdown link parser.
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="sd">This module provides fast parsing of Markdown links,
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="sd">compatible with the original Python implementation.
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="sd">Build:
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="sd">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="sd">Usage:
</span></span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="sd">    from markdown_parser import parse_markdown_links
</span></span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="sd">    links = parse_markdown_links(markdown_content)
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">
</span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="k">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="k">from</span> <span class="nn">typing</span> <span class="k">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">
</span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c"># Compiled regex patterns (module level for reuse)</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">
</span></span><span class="line"><span class="ln"> 23</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="s">r&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">
</span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">    <span class="s">r&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">    <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">
</span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">    <span class="s">r&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">
</span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="c"># C-level data structures</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">
</span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">LinkInfo</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 42</span><span class="cl"><span class="sd">    C-level struct to hold link information.
</span></span></span><span class="line"><span class="ln"> 43</span><span class="cl"><span class="sd">    Faster than Python dict for internal operations.
</span></span></span><span class="line"><span class="ln"> 44</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">text</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">target</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">int</span> <span class="nf">line</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">str</span> <span class="n">text</span><span class="p">,</span> <span class="nb">str</span> <span class="n">target</span><span class="p">,</span> <span class="nb">int</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">line</span> <span class="o">=</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">    <span class="k">def</span> <span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">        <span class="sd">&#34;&#34;&#34;Convert to dictionary for API compatibility.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">        <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">            <span class="s">&#34;text&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">            <span class="s">&#34;target&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">            <span class="s">&#34;line&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">line</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">return</span> <span class="n">f</span><span class="s">&#34;LinkInfo(text={self.text!r}, target={self.target!r}, line={self.line})&#34;</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">
</span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl"><span class="c"># Internal helper functions (cdef = C-only, fastest)</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">
</span></span><span class="line"><span class="ln"> 69</span><span class="cl"><span class="k">cdef</span> <span class="kt">bint</span> <span class="nf">is_code_fence</span><span class="p">(</span><span class="nb">str</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="sd">    Check if line is a code fence marker.
</span></span></span><span class="line"><span class="ln"> 72</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="k">cdef</span> <span class="kt">str</span> <span class="nf">stripped</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="k">return</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;```&#34;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;~~~&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">
</span></span><span class="line"><span class="ln"> 76</span><span class="cl"><span class="k">cdef</span> <span class="kt">dict</span> <span class="nf">_collect_reference_defs</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="sd">    Collect reference link definitions from content.
</span></span></span><span class="line"><span class="ln"> 79</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">    <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">        <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="n">ref_target</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="k">return</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">
</span></span><span class="line"><span class="ln"> 93</span><span class="cl"><span class="k">cdef</span> <span class="kt">list</span> <span class="nf">_parse_inline_links</span><span class="p">(</span><span class="nb">list</span> <span class="n">lines</span><span class="p">,</span> <span class="nb">dict</span> <span class="n">reference_defs</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="sd">    Parse inline and reference links from lines.
</span></span></span><span class="line"><span class="ln"> 96</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">        <span class="nb">list</span> <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">        <span class="nb">int</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">        <span class="nb">int</span> <span class="n">total_lines</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="n">bint</span> <span class="n">in_code_block</span> <span class="o">=</span> <span class="bp">False</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="nb">str</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="k">for</span> <span class="n">line_num</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">total_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">        <span class="n">line</span> <span class="o">=</span> <span class="n">lines</span><span class="p">[</span><span class="n">line_num</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">
</span></span><span class="line"><span class="ln">109</span><span class="cl">        <span class="c"># Check code fence</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="k">if</span> <span class="n">is_code_fence</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">            <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">
</span></span><span class="line"><span class="ln">114</span><span class="cl">        <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">
</span></span><span class="line"><span class="ln">117</span><span class="cl">        <span class="c"># Parse inline links [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">            <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">                <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">            <span class="p">))</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">        <span class="c"># Parse reference links [text][ref]</span>
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">            <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">                    <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">                    <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">                    <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">                <span class="p">))</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">
</span></span><span class="line"><span class="ln">135</span><span class="cl">    <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">
</span></span><span class="line"><span class="ln">137</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl"><span class="c"># Public API (cpdef = callable from both Python and Cython)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="k">cpdef</span> <span class="kt">list</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">143</span><span class="cl"><span class="sd">    Parse all links from Markdown content.
</span></span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">145</span><span class="cl"><span class="sd">    Args:
</span></span></span><span class="line"><span class="ln">146</span><span class="cl"><span class="sd">        content: Markdown content string
</span></span></span><span class="line"><span class="ln">147</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">148</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">149</span><span class="cl"><span class="sd">        List of dicts with &#39;text&#39;, &#39;target&#39;, &#39;line&#39; keys
</span></span></span><span class="line"><span class="ln">150</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">151</span><span class="cl"><span class="sd">    Example:
</span></span></span><span class="line"><span class="ln">152</span><span class="cl"><span class="sd">        &gt;&gt;&gt; content = &#34;[Click here](https://example.com)&#34;
</span></span></span><span class="line"><span class="ln">153</span><span class="cl"><span class="sd">        &gt;&gt;&gt; links = parse_markdown_links(content)
</span></span></span><span class="line"><span class="ln">154</span><span class="cl"><span class="sd">        &gt;&gt;&gt; links[0][&#39;target&#39;]
</span></span></span><span class="line"><span class="ln">155</span><span class="cl"><span class="sd">        &#39;https://example.com&#39;
</span></span></span><span class="line"><span class="ln">156</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">157</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">158</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">159</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">160</span><span class="cl">        <span class="nb">list</span> <span class="n">link_infos</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">        <span class="nb">list</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">162</span><span class="cl">        <span class="n">LinkInfo</span> <span class="n">info</span>
</span></span><span class="line"><span class="ln">163</span><span class="cl">
</span></span><span class="line"><span class="ln">164</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">166</span><span class="cl">    <span class="n">link_infos</span> <span class="o">=</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">167</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">info</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">info</span> <span class="ow">in</span> <span class="n">link_infos</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">
</span></span><span class="line"><span class="ln">169</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">
</span></span><span class="line"><span class="ln">171</span><span class="cl"><span class="c"># Python-compatible wrapper with full type hints</span>
</span></span><span class="line"><span class="ln">172</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_py</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">173</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">174</span><span class="cl"><span class="sd">    Python-compatible wrapper with type hints.
</span></span></span><span class="line"><span class="ln">175</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">176</span><span class="cl"><span class="sd">    Identical to parse_markdown_links but with explicit
</span></span></span><span class="line"><span class="ln">177</span><span class="cl"><span class="sd">    Python type annotations for better IDE support.
</span></span></span><span class="line"><span class="ln">178</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl">    <span class="k">return</span> <span class="n">parse_markdown_links</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">
</span></span><span class="line"><span class="ln">181</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl"><span class="c"># Optional: Expose LinkInfo class for advanced usage</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">184</span><span class="cl">
</span></span><span class="line"><span class="ln">185</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_fast</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">186</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">187</span><span class="cl"><span class="sd">    Parse links and return LinkInfo objects directly.
</span></span></span><span class="line"><span class="ln">188</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">189</span><span class="cl"><span class="sd">    Faster than parse_markdown_links() as it skips
</span></span></span><span class="line"><span class="ln">190</span><span class="cl"><span class="sd">    the dict conversion step.
</span></span></span><span class="line"><span class="ln">191</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">193</span><span class="cl"><span class="sd">        List of LinkInfo objects
</span></span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">198</span><span class="cl">
</span></span><span class="line"><span class="ln">199</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl">    <span class="k">return</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span></span></span></code></pre></div><h3 id="效能比較">效能比較</h3>
<p>建立效能測試腳本來比較純 Python 和 Cython 版本：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1"># benchmark.py</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="s2">Performance comparison between Python and Cython implementations.
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="s2">Usage:
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="s2">    # First, build the Cython module
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="s2">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="s2">    # Then run benchmark
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="s2">    python benchmark.py
</span></span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">List</span>
</span></span><span class="line"><span class="ln"> 16</span><span class="cl">
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="c1"># Pure Python implementation (inline for comparison)</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">
</span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="k">class</span> <span class="nc">PythonMarkdownParser</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Original pure Python implementation.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">    <span class="n">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="n">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">    <span class="n">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">    <span class="k">def</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">        <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">        <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">        <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">        <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">            <span class="n">ref_target</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">            <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">        <span class="n">in_code_block</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">        <span class="k">for</span> <span class="n">line_num</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">            <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">                <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">            <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">                    <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">                    <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">                    <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">                <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">                <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">                    <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">                        <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">                        <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">                        <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">                    <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">
</span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="k">def</span> <span class="nf">generate_test_content</span><span class="p">(</span><span class="n">num_lines</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">links_per_100_lines</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Generate test Markdown content with specified characteristics.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">        <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="p">(</span><span class="mi">100</span> <span class="o">//</span> <span class="n">links_per_100_lines</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">            <span class="c1"># Add an inline link</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Check out [Link </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">](https://example.com/page</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">) for details.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">        <span class="k">elif</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">50</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">            <span class="c1"># Add a code block</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;```python&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;# This is code, links here [should](/python-advanced/05-c-extensions/case-studies/cython-markdown/be/ignored)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">            <span class="c1"># Regular text</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;This is line </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2"> with some regular text content.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="k">return</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">
</span></span><span class="line"><span class="ln"> 83</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Run benchmark and return statistics.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="c1"># Warmup</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">func</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="c1"># Actual benchmark</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">        <span class="s2">&#34;mean&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>  <span class="c1"># Convert to ms</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">        <span class="s2">&#34;stdev&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="s2">&#34;min&#34;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="s2">&#34;max&#34;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">        <span class="s2">&#34;links_found&#34;</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Markdown Link Parser Benchmark&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">
</span></span><span class="line"><span class="ln">111</span><span class="cl">    <span class="c1"># Test different content sizes</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">    <span class="n">sizes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1000</span><span class="p">,</span> <span class="mi">5000</span><span class="p">,</span> <span class="mi">10000</span><span class="p">,</span> <span class="mi">50000</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">
</span></span><span class="line"><span class="ln">114</span><span class="cl">    <span class="n">python_parser</span> <span class="o">=</span> <span class="n">PythonMarkdownParser</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">
</span></span><span class="line"><span class="ln">116</span><span class="cl">    <span class="c1"># Try to import Cython version</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">        <span class="kn">from</span> <span class="nn">markdown_parser</span> <span class="kn">import</span> <span class="n">parse_markdown_links</span> <span class="k">as</span> <span class="n">cython_parse</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">        <span class="n">has_cython</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">    <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Warning: Cython module not found.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Run &#39;python setup.py build_ext --inplace&#39; first.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">        <span class="n">has_cython</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">    <span class="k">for</span> <span class="n">size</span> <span class="ow">in</span> <span class="n">sizes</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">--- Content size: </span><span class="si">{</span><span class="n">size</span><span class="si">}</span><span class="s2"> lines ---&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">        <span class="n">content</span> <span class="o">=</span> <span class="n">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="c1"># Python benchmark</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">        <span class="n">py_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">python_parser</span><span class="o">.</span><span class="n">parse_markdown_links</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Python:  </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms (+/- </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;         Found </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;links_found&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> links&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">
</span></span><span class="line"><span class="ln">134</span><span class="cl">        <span class="c1"># Cython benchmark (if available)</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">        <span class="k">if</span> <span class="n">has_cython</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">            <span class="n">cy_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cython_parse</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">            <span class="n">speedup</span> <span class="o">=</span> <span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Cython:  </span><span class="si">{</span><span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms (+/- </span><span class="si">{</span><span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;         Speedup: </span><span class="si">{</span><span class="n">speedup</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">
</span></span><span class="line"><span class="ln">143</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">144</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h3 id="預期結果">預期結果</h3>
<p>執行效能測試後，預期會看到類似以下的結果：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">Markdown Link Parser Benchmark
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">--- Content size: 1000 lines ---
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Python:  0.523 ms (+/- 0.031 ms)
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">         Found 100 links
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">Cython:  0.198 ms (+/- 0.012 ms)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">         Speedup: 2.64x
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">--- Content size: 5000 lines ---
</span></span><span class="line"><span class="ln">12</span><span class="cl">Python:  2.617 ms (+/- 0.089 ms)
</span></span><span class="line"><span class="ln">13</span><span class="cl">         Found 500 links
</span></span><span class="line"><span class="ln">14</span><span class="cl">Cython:  0.892 ms (+/- 0.045 ms)
</span></span><span class="line"><span class="ln">15</span><span class="cl">         Speedup: 2.93x
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">--- Content size: 10000 lines ---
</span></span><span class="line"><span class="ln">18</span><span class="cl">Python:  5.234 ms (+/- 0.156 ms)
</span></span><span class="line"><span class="ln">19</span><span class="cl">         Found 1000 links
</span></span><span class="line"><span class="ln">20</span><span class="cl">Cython:  1.712 ms (+/- 0.078 ms)
</span></span><span class="line"><span class="ln">21</span><span class="cl">         Speedup: 3.06x
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">--- Content size: 50000 lines ---
</span></span><span class="line"><span class="ln">24</span><span class="cl">Python:  26.18 ms (+/- 0.823 ms)
</span></span><span class="line"><span class="ln">25</span><span class="cl">         Found 5000 links
</span></span><span class="line"><span class="ln">26</span><span class="cl">Cython:  7.89 ms (+/- 0.312 ms)
</span></span><span class="line"><span class="ln">27</span><span class="cl">         Speedup: 3.32x
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">============================================================</span></span></code></pre></div><p><strong>結果分析</strong>：</p>
<table>
  <thead>
      <tr>
          <th>內容大小</th>
          <th>Python</th>
          <th>Cython</th>
          <th>加速比</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1,000 行</td>
          <td>0.52 ms</td>
          <td>0.20 ms</td>
          <td>2.6x</td>
      </tr>
      <tr>
          <td>5,000 行</td>
          <td>2.62 ms</td>
          <td>0.89 ms</td>
          <td>2.9x</td>
      </tr>
      <tr>
          <td>10,000 行</td>
          <td>5.23 ms</td>
          <td>1.71 ms</td>
          <td>3.1x</td>
      </tr>
      <tr>
          <td>50,000 行</td>
          <td>26.2 ms</td>
          <td>7.89 ms</td>
          <td>3.3x</td>
      </tr>
  </tbody>
</table>
<p>觀察：</p>
<ul>
<li>加速比隨著資料量增加而提高</li>
<li>主要效能提升來自迴圈優化和型別化變數</li>
<li>正則表達式仍然是瓶頸（Cython 無法加速 <code>re</code> 模組本身）</li>
</ul>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>純 Python</th>
          <th>Cython</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>開發速度</strong></td>
          <td>快，即寫即用</td>
          <td>中，需要編譯步驟</td>
      </tr>
      <tr>
          <td><strong>執行速度</strong></td>
          <td>基準</td>
          <td>2-5x 加速</td>
      </tr>
      <tr>
          <td><strong>除錯難度</strong></td>
          <td>低，標準 Python 工具</td>
          <td>中，需要看生成的 C 碼</td>
      </tr>
      <tr>
          <td><strong>部署複雜度</strong></td>
          <td>簡單，純 Python</td>
          <td>需要編譯環境或預編譯 wheel</td>
      </tr>
      <tr>
          <td><strong>可維護性</strong></td>
          <td>高</td>
          <td>中，需要了解 Cython 語法</td>
      </tr>
      <tr>
          <td><strong>IDE 支援</strong></td>
          <td>完整</td>
          <td>部分（.pyx 支援有限）</td>
      </tr>
      <tr>
          <td><strong>跨平台</strong></td>
          <td>天生跨平台</td>
          <td>需要為每個平台編譯</td>
      </tr>
  </tbody>
</table>
<h2 id="進階優化使用-c-正則表達式">進階優化：使用 C 正則表達式</h2>
<p>如果需要更高的效能，可以考慮使用 C 語言的正則表達式庫。以下是使用 PCRE2 的範例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># advanced_parser.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="sd">Advanced parser using PCRE2 C library for maximum performance.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">Requires: libpcre2-dev (Ubuntu) or pcre2 (macOS Homebrew)
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">&#34;pcre2.h&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c"># PCRE2 declarations...</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">pass</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c"># This is an advanced topic, see PCRE2 documentation for details</span></span></span></code></pre></div><p>不過，對於大多數使用情境，Python 的 <code>re</code> 模組配合 Cython 優化的迴圈已經足夠。</p>
<h2 id="什麼時候該用-cython">什麼時候該用 Cython？</h2>
<h3 id="適合使用">適合使用</h3>
<ul>
<li>熱點程式碼已經用 profiler 確認</li>
<li>需要 2x 以上的效能提升</li>
<li>程式碼相對穩定，不常變動</li>
<li>團隊有能力維護 Cython 程式碼</li>
<li>可以接受編譯步驟</li>
</ul>
<h3 id="不建議使用">不建議使用</h3>
<ul>
<li>效能瓶頸在 I/O（網路、磁碟）</li>
<li>程式碼還在頻繁迭代中</li>
<li>跨平台部署且沒有 CI/CD 支援</li>
<li>團隊對 C 語言不熟悉</li>
<li>效能提升不到 2x</li>
</ul>
<h3 id="替代方案考量">替代方案考量</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">如果 Cython 不適合你的情境，考慮：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">1. PyPy
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">   - 無需修改程式碼
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">   - JIT 編譯帶來 5-10x 加速
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">   - 但相容性問題較多
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">2. Numba
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">   - 針對數值計算優化
</span></span><span class="line"><span class="ln">10</span><span class="cl">   - 使用裝飾器即可加速
</span></span><span class="line"><span class="ln">11</span><span class="cl">   - 但僅支援部分 Python 語法
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">3. 演算法優化
</span></span><span class="line"><span class="ln">14</span><span class="cl">   - 先檢查是否有更好的演算法
</span></span><span class="line"><span class="ln">15</span><span class="cl">   - 減少不必要的記憶體分配
</span></span><span class="line"><span class="ln">16</span><span class="cl">   - 使用更高效的資料結構</span></span></code></pre></div><h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>將以下純 Python 函式轉換為 Cython：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># exercise_1.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">count_words</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Count word frequencies in text.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">words</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">counts</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="n">word</span> <span class="o">=</span> <span class="n">word</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;.,!?;:&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">if</span> <span class="n">word</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="n">counts</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="n">counts</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">counts</span></span></span></code></pre></div><p>提示：</p>
<ol>
<li>建立 <code>exercise_1.pyx</code></li>
<li>為 <code>counts</code> 變數添加 <code>cdef dict</code> 宣告</li>
<li>為迴圈變數添加適當的型別宣告</li>
<li>考慮使用 <code>cdef</code> 輔助函式處理字串清理</li>
</ol>
<h3 id="進階練習">進階練習</h3>
<p>使用 cProfile 驗證 Cython 加速效果：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># exercise_2.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">cProfile</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">pstats</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">profile_parsers</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Profile both Python and Cython parsers.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="kn">from</span> <span class="nn">markdown_parser</span> <span class="kn">import</span> <span class="n">parse_markdown_links</span> <span class="k">as</span> <span class="n">cython_parse</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">python_parser</span> <span class="o">=</span> <span class="n">PythonMarkdownParser</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1"># Profile Python version</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=== Python Version ===&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">cProfile</span><span class="o">.</span><span class="n">runctx</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s1">&#39;for _ in range(100): python_parser.parse_markdown_links(content)&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="nb">globals</span><span class="p">(),</span> <span class="nb">locals</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="s1">&#39;python_stats&#39;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s1">&#39;python_stats&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s1">&#39;cumulative&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># Profile Cython version</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">=== Cython Version ===&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">cProfile</span><span class="o">.</span><span class="n">runctx</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s1">&#39;for _ in range(100): cython_parse(content)&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="nb">globals</span><span class="p">(),</span> <span class="nb">locals</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="s1">&#39;cython_stats&#39;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s1">&#39;cython_stats&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s1">&#39;cumulative&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span></span></span></code></pre></div><h3 id="挑戰題">挑戰題</h3>
<p>比較不同型別宣告策略的效能影響：</p>
<ol>
<li><strong>無型別宣告</strong>：將 <code>.pyx</code> 當作純 Python 編譯</li>
<li><strong>部分型別宣告</strong>：只為迴圈變數添加型別</li>
<li><strong>完整型別宣告</strong>：為所有變數添加型別</li>
<li><strong>使用 LinkInfo 類別</strong> vs <strong>使用 dict</strong></li>
</ol>
<p>記錄每種策略的效能，並分析哪些優化帶來最大效益。</p>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://cython.readthedocs.io/">Cython 官方文件</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html">Cython 最佳實踐</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html">Cython 與 NumPy 整合</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/userguide/debugging.html">Cython 產生的 C 程式碼分析</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組四：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>案例：使用 ctypes 呼叫系統 API</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/</guid><description>&lt;p>本案例展示如何使用 ctypes 直接呼叫系統 API，處理 Python 標準庫未提供的底層功能。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">4.1 ctypes 與 cffi：動態綁定&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="為什麼需要直接呼叫系統-api">為什麼需要直接呼叫系統 API？&lt;/h3>
&lt;p>Python 標準庫涵蓋了大多數常見需求，但有時我們需要：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>存取特定系統功能&lt;/strong>：某些底層功能沒有 Python 封裝&lt;/li>
&lt;li>&lt;strong>避免 subprocess 開銷&lt;/strong>：執行外部命令有進程建立的成本&lt;/li>
&lt;li>&lt;strong>即時取得系統資訊&lt;/strong>：某些資訊需要直接從核心取得&lt;/li>
&lt;li>&lt;strong>與 C 函式庫互動&lt;/strong>：使用第三方 C 函式庫的功能&lt;/li>
&lt;/ul>
&lt;h3 id="常見場景">常見場景&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">需要直接呼叫系統 API 的情況：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── 取得主機名稱（gethostname）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── 取得使用者 ID（getuid, geteuid）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 系統時間操作（time, gettimeofday）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├── 檔案系統操作（sync, fsync）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">├── 記憶體資訊（sysinfo - Linux 限定）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└── 其他未封裝的 POSIX/Windows API&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>雖然許多功能有 Python 對應（如 &lt;code>os.getpid()&lt;/code>、&lt;code>socket.gethostname()&lt;/code>），但理解如何直接呼叫系統 API 是重要的技能：&lt;/p>
&lt;ol>
&lt;li>學習 ctypes 的實際應用&lt;/li>
&lt;li>處理 Python 未封裝的功能&lt;/li>
&lt;li>理解 Python 標準庫的實作原理&lt;/li>
&lt;/ol>
&lt;h2 id="實作方案">實作方案&lt;/h2>
&lt;h3 id="基礎設置跨平台載入-libc">基礎設置：跨平台載入 libc&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># system_api.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="s2">使用 ctypes 呼叫系統 API 的範例模組。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s2">跨平台支援 Linux、macOS 和 Windows。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes.util&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Optional&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">load_libc&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2"> 跨平台載入 C 函式庫。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s2"> ctypes.CDLL: 載入的 C 函式庫物件
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="s2"> Raises:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="s2"> OSError: 無法載入 C 函式庫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Windows 使用 msvcrt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;msvcrt&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Unix-like 系統使用 find_library&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">libc_name&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 嘗試常見路徑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;darwin&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;libc.dylib&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;libc.so.6&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">libc_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="c1"># 全域 libc 實例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="n">_libc&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_libc&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得 libc 的單例實例。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="k">global&lt;/span> &lt;span class="n">_libc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">_libc&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="n">_libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">_libc&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-1取得主機名稱">範例 1：取得主機名稱&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">socket&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gethostname_ctypes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 gethostname() 取得主機名稱。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> max_len: 主機名稱緩衝區大小
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> 主機名稱字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> Raises:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2"> OSError: 系統呼叫失敗
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="c1"># int gethostname(char *name, size_t len)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 建立緩衝區&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 呼叫系統函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gethostname failed with code &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">&lt;span class="c1"># 比較 ctypes 與 Python 標準庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes gethostname: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;socket.gethostname: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">socket&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-2取得-process-id">範例 2：取得 Process ID&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 getpid() 取得當前 process ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> 當前 process 的 PID
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># pid_t getpid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getppid_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 getppid() 取得父 process ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> 父 process 的 PID
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="c1"># pid_t getppid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes getpid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os.getpid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes getppid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">getppid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os.getppid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-3unix-時間戳記">範例 3：Unix 時間戳記&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">time_module&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">time_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 time() 取得 Unix 時間戳記。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> 當前 Unix 時間戳記（秒）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># time_t time(time_t *tloc)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 傳入 NULL，直接取得回傳值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="c1"># timeval 結構體（用於 gettimeofday）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Timeval&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Structure&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> struct timeval {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> time_t tv_sec; // 秒
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="s2"> suseconds_t tv_usec; // 微秒
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="s2"> };
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="n">_fields_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tv_sec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tv_usec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gettimeofday_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">tuple&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 gettimeofday() 取得高精度時間。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="s2"> (秒, 微秒) 的 tuple
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="s2"> Note:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="s2"> gettimeofday 在 POSIX.1-2008 中已標記為過時，
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl">&lt;span class="s2"> 建議使用 clock_gettime。此處僅作為教學範例。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday not available on Windows&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="c1"># int gettimeofday(struct timeval *tv, struct timezone *tz)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">POINTER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Timeval&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span> &lt;span class="c1"># timezone 已過時，傳 NULL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl"> &lt;span class="n">tv&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Timeval&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">byref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tv&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday failed with code &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tv&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tv_sec&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tv&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tv_usec&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">65&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">66&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">67&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes time: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">68&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;time.time: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">time_module&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">69&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">70&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">71&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">72&lt;/span>&lt;span class="cl"> &lt;span class="n">sec&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">usec&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gettimeofday_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">73&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">sec&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">usec&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">06d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-4使用者與群組-idunix-限定">範例 4：使用者與群組 ID（Unix 限定）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_user_ids&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> 取得當前 process 的使用者和群組 ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> 包含 uid, euid, gid, egid 的字典
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> Note:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2"> 僅支援 Unix-like 系統。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;User IDs not applicable on Windows&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 設定函式簽名&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="c1"># uid_t getuid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="c1"># uid_t geteuid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="c1"># gid_t getgid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="c1"># gid_t getegid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;uid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;euid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;gid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;egid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_user_ids&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes: uid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;uid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, euid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;euid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;gid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, egid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;egid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os: uid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, euid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, egid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="跨平台考量">跨平台考量&lt;/h2>
&lt;h3 id="平台差異對照表">平台差異對照表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>Linux&lt;/th>
 &lt;th>macOS&lt;/th>
 &lt;th>Windows&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>libc 名稱&lt;/td>
 &lt;td>&lt;code>libc.so.6&lt;/code>&lt;/td>
 &lt;td>&lt;code>libc.dylib&lt;/code>&lt;/td>
 &lt;td>&lt;code>msvcrt&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gethostname&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>kernel32.GetComputerNameA&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>getpid&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>kernel32.GetCurrentProcessId&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>time&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>msvcrt.time&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>getuid/geteuid&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>不適用&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="windows-特定實作">Windows 特定實作&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gethostname_windows&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> Windows 版本的 gethostname。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 kernel32.GetComputerNameA。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;This function is Windows-only&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">windll&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kernel32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="c1"># BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_ulong&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetComputerNameA&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">byref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;GetComputerNameA failed&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getpid_windows&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="s2"> Windows 版本的 getpid。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 kernel32.GetCurrentProcessId。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;This function is Windows-only&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">windll&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kernel32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="c1"># DWORD GetCurrentProcessId(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_ulong&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="p">()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="跨平台封裝">跨平台封裝&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_hostname&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;跨平台取得主機名稱。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_windows&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_process_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;跨平台取得 process ID。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">getpid_windows&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="錯誤處理與安全性">錯誤處理與安全性&lt;/h2>
&lt;h3 id="常見錯誤類型">常見錯誤類型&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">errno&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">safe_gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 安全版本的 gethostname，包含完整的錯誤處理。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 設定函式簽名&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 驗證參數&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">max_len&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;max_len must be positive&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">max_len&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1024&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;max_len too large (max 1024)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 建立緩衝區&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 呼叫系統函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 取得錯誤碼&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="n">err&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_errno&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">err&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENAMETOOLONG&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENAMETOOLONG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;Hostname too long for buffer&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">err&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EFAULT&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EFAULT&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;Invalid buffer address&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gethostname failed: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">errorcode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Unknown&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 解碼並處理可能的編碼錯誤&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="ne">UnicodeDecodeError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;latin-1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="安全性考量">安全性考量&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="s2">使用 ctypes 時的安全性注意事項：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s2">1. 緩衝區溢位
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 永遠確保緩衝區大小足夠
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 使用 create_string_buffer() 而非直接操作指標
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2">2. 型別安全
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 務必設定 argtypes 和 restype
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 錯誤的型別可能導致程式崩潰或安全漏洞
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2">3. 記憶體管理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2"> - ctypes 物件由 Python GC 管理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 小心回呼函式的生命週期
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">4. 輸入驗證
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 永遠驗證使用者輸入
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 不要直接將未驗證的資料傳給 C 函式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">secure_strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> 安全的 strlen 範例，包含輸入驗證。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 輸入驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="nb">isinstance&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">TypeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Expected str, got {type(s).__name__}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 限制長度避免 DoS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">MAX_LENGTH&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10_000_000&lt;/span> &lt;span class="c1"># 10 MB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">MAX_LENGTH&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;String too long (max &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">MAX_LENGTH&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> bytes)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 轉換為 bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="n">encoded&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">encoded&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="錯誤碼處理">錯誤碼處理&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">errno&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得錯誤碼對應的訊息。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1"># char *strerror(int errnum)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Unknown error &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="c1"># 使用範例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ENOENT (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENOENT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENOENT&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;EACCES (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EACCES&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EACCES&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;EINVAL (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EINVAL&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EINVAL&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="效能比較ctypes-vs-subprocess">效能比較：ctypes vs subprocess&lt;/h2>
&lt;h3 id="測試腳本">測試腳本&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">subprocess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">statistics&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Callable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Callable&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;執行效能測試並回傳統計資料。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">times&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 暖機&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">func&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 實際測試&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">func&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">times&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;mean&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">statistics&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 轉換為微秒&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;stdev&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">statistics&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdev&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;min&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;max&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 1：ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_ctypes&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 2：subprocess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_subprocess&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;hostname&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="n">capture_output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 3：Python 標準庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_stdlib&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">socket&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">socket&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl">&lt;span class="c1"># 執行測試&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;取得主機名稱效能比較&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="n">methods&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ctypes&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_ctypes&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;subprocess&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_subprocess&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;socket (stdlib)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_stdlib&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">func&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">methods&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 平均: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;mean&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 標準差: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;stdev&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 最小: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;min&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 最大: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;max&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="效能測試結果">效能測試結果&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">============================================================
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">取得主機名稱效能比較
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">============================================================
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">ctypes:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> 平均: 1.52 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 標準差: 0.31 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 最小: 1.21 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 最大: 8.45 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">subprocess:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> 平均: 4523.67 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> 標準差: 892.34 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> 最小: 3128.45 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> 最大: 12456.78 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">socket (stdlib):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> 平均: 0.89 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> 標準差: 0.18 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> 最小: 0.72 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> 最大: 4.23 us&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="結果分析">結果分析&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>方法&lt;/th>
 &lt;th>平均時間&lt;/th>
 &lt;th>相對 ctypes&lt;/th>
 &lt;th>適用場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>socket (stdlib)&lt;/strong>&lt;/td>
 &lt;td>~0.9 us&lt;/td>
 &lt;td>0.6x (最快)&lt;/td>
 &lt;td>首選，已有封裝&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>ctypes&lt;/strong>&lt;/td>
 &lt;td>~1.5 us&lt;/td>
 &lt;td>1x (基準)&lt;/td>
 &lt;td>無標準庫支援時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>subprocess&lt;/strong>&lt;/td>
 &lt;td>~4500 us&lt;/td>
 &lt;td>~3000x (最慢)&lt;/td>
 &lt;td>需要執行外部命令時&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>結論&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>本案例展示如何使用 ctypes 直接呼叫系統 API，處理 Python 標準庫未提供的底層功能。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">4.1 ctypes 與 cffi：動態綁定</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="為什麼需要直接呼叫系統-api">為什麼需要直接呼叫系統 API？</h3>
<p>Python 標準庫涵蓋了大多數常見需求，但有時我們需要：</p>
<ul>
<li><strong>存取特定系統功能</strong>：某些底層功能沒有 Python 封裝</li>
<li><strong>避免 subprocess 開銷</strong>：執行外部命令有進程建立的成本</li>
<li><strong>即時取得系統資訊</strong>：某些資訊需要直接從核心取得</li>
<li><strong>與 C 函式庫互動</strong>：使用第三方 C 函式庫的功能</li>
</ul>
<h3 id="常見場景">常見場景</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">需要直接呼叫系統 API 的情況：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 取得主機名稱（gethostname）
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 取得使用者 ID（getuid, geteuid）
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 系統時間操作（time, gettimeofday）
</span></span><span class="line"><span class="ln">5</span><span class="cl">├── 檔案系統操作（sync, fsync）
</span></span><span class="line"><span class="ln">6</span><span class="cl">├── 記憶體資訊（sysinfo - Linux 限定）
</span></span><span class="line"><span class="ln">7</span><span class="cl">└── 其他未封裝的 POSIX/Windows API</span></span></code></pre></div><p>雖然許多功能有 Python 對應（如 <code>os.getpid()</code>、<code>socket.gethostname()</code>），但理解如何直接呼叫系統 API 是重要的技能：</p>
<ol>
<li>學習 ctypes 的實際應用</li>
<li>處理 Python 未封裝的功能</li>
<li>理解 Python 標準庫的實作原理</li>
</ol>
<h2 id="實作方案">實作方案</h2>
<h3 id="基礎設置跨平台載入-libc">基礎設置：跨平台載入 libc</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># system_api.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">使用 ctypes 呼叫系統 API 的範例模組。
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">跨平台支援 Linux、macOS 和 Windows。
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes.util</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="k">def</span> <span class="nf">load_libc</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">    跨平台載入 C 函式庫。
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">        ctypes.CDLL: 載入的 C 函式庫物件
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">    Raises:
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">        OSError: 無法載入 C 函式庫
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="c1"># Windows 使用 msvcrt</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="k">return</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s1">&#39;msvcrt&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="c1"># Unix-like 系統使用 find_library</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">libc_name</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="k">if</span> <span class="n">libc_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">            <span class="c1"># 嘗試常見路徑</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;darwin&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                <span class="n">libc_name</span> <span class="o">=</span> <span class="s1">&#39;libc.dylib&#39;</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">                <span class="n">libc_name</span> <span class="o">=</span> <span class="s1">&#39;libc.so.6&#39;</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="k">return</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">libc_name</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="c1"># 全域 libc 實例</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="n">_libc</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="k">def</span> <span class="nf">get_libc</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="s2">&#34;&#34;&#34;取得 libc 的單例實例。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="k">global</span> <span class="n">_libc</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="k">if</span> <span class="n">_libc</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="n">_libc</span> <span class="o">=</span> <span class="n">load_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">    <span class="k">return</span> <span class="n">_libc</span></span></span></code></pre></div><h3 id="範例-1取得主機名稱">範例 1：取得主機名稱</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">gethostname_ctypes</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 gethostname() 取得主機名稱。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Args:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        max_len: 主機名稱緩衝區大小
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">        主機名稱字串
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">    Raises:
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">        OSError: 系統呼叫失敗
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1"># int gethostname(char *name, size_t len)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c1"># 建立緩衝區</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="c1"># 呼叫系統函式</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gethostname failed with code </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1"># 比較 ctypes 與 Python 標準庫</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes gethostname: </span><span class="si">{</span><span class="n">gethostname_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;socket.gethostname: </span><span class="si">{</span><span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-2取得-process-id">範例 2：取得 Process ID</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">getpid_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 getpid() 取得當前 process ID。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        當前 process 的 PID
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># pid_t getpid(void)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">def</span> <span class="nf">getppid_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 getppid() 取得父 process ID。
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        父 process 的 PID
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="c1"># pid_t getppid(void)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes getpid: </span><span class="si">{</span><span class="n">getpid_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os.getpid: </span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes getppid: </span><span class="si">{</span><span class="n">getppid_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os.getppid: </span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getppid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-3unix-時間戳記">範例 3：Unix 時間戳記</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span> <span class="k">as</span> <span class="nn">time_module</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">time_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 time() 取得 Unix 時間戳記。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        當前 Unix 時間戳記（秒）
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># time_t time(time_t *tloc)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="c1"># 傳入 NULL，直接取得回傳值</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># timeval 結構體（用於 gettimeofday）</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="k">class</span> <span class="nc">Timeval</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">Structure</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    struct timeval {
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        time_t      tv_sec;   // 秒
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">        suseconds_t tv_usec;  // 微秒
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">    };
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;tv_sec&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;tv_usec&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="k">def</span> <span class="nf">gettimeofday_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 gettimeofday() 取得高精度時間。
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="s2">        (秒, 微秒) 的 tuple
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="s2">    Note:
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="s2">        gettimeofday 在 POSIX.1-2008 中已標記為過時，
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="s2">        建議使用 clock_gettime。此處僅作為教學範例。
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;gettimeofday not available on Windows&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">
</span></span><span class="line"><span class="ln">48</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="c1"># int gettimeofday(struct timeval *tv, struct timezone *tz)</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">        <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">Timeval</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">        <span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span>  <span class="c1"># timezone 已過時，傳 NULL</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">
</span></span><span class="line"><span class="ln">57</span><span class="cl">    <span class="n">tv</span> <span class="o">=</span> <span class="n">Timeval</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">tv</span><span class="p">),</span> <span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">
</span></span><span class="line"><span class="ln">60</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gettimeofday failed with code </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">
</span></span><span class="line"><span class="ln">63</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">tv</span><span class="o">.</span><span class="n">tv_sec</span><span class="p">,</span> <span class="n">tv</span><span class="o">.</span><span class="n">tv_usec</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">
</span></span><span class="line"><span class="ln">65</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">66</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">67</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes time: </span><span class="si">{</span><span class="n">time_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">68</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;time.time: </span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">time_module</span><span class="o">.</span><span class="n">time</span><span class="p">())</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">69</span><span class="cl">
</span></span><span class="line"><span class="ln">70</span><span class="cl">    <span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">71</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">72</span><span class="cl">        <span class="n">sec</span><span class="p">,</span> <span class="n">usec</span> <span class="o">=</span> <span class="n">gettimeofday_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">73</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gettimeofday: </span><span class="si">{</span><span class="n">sec</span><span class="si">}</span><span class="s2">.</span><span class="si">{</span><span class="n">usec</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-4使用者與群組-idunix-限定">範例 4：使用者與群組 ID（Unix 限定）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">get_user_ids</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    取得當前 process 的使用者和群組 ID。
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">        包含 uid, euid, gid, egid 的字典
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">    Note:
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">        僅支援 Unix-like 系統。
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;User IDs not applicable on Windows&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="c1"># 設定函式簽名</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># uid_t getuid(void)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="c1"># uid_t geteuid(void)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c1"># gid_t getgid(void)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="c1"># gid_t getegid(void)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="s1">&#39;uid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">        <span class="s1">&#39;euid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">        <span class="s1">&#39;gid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="s1">&#39;egid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">        <span class="n">ids</span> <span class="o">=</span> <span class="n">get_user_ids</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes: uid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;uid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, euid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;euid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, &#34;</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">              <span class="sa">f</span><span class="s2">&#34;gid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;gid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, egid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;egid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os: uid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getuid</span><span class="p">()</span><span class="si">}</span><span class="s2">, euid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">geteuid</span><span class="p">()</span><span class="si">}</span><span class="s2">, &#34;</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">              <span class="sa">f</span><span class="s2">&#34;gid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getgid</span><span class="p">()</span><span class="si">}</span><span class="s2">, egid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getegid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h2 id="跨平台考量">跨平台考量</h2>
<h3 id="平台差異對照表">平台差異對照表</h3>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>Linux</th>
          <th>macOS</th>
          <th>Windows</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>libc 名稱</td>
          <td><code>libc.so.6</code></td>
          <td><code>libc.dylib</code></td>
          <td><code>msvcrt</code></td>
      </tr>
      <tr>
          <td><code>gethostname</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>kernel32.GetComputerNameA</code></td>
      </tr>
      <tr>
          <td><code>getpid</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>kernel32.GetCurrentProcessId</code></td>
      </tr>
      <tr>
          <td><code>time</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>msvcrt.time</code></td>
      </tr>
      <tr>
          <td><code>getuid/geteuid</code></td>
          <td>libc</td>
          <td>libc</td>
          <td>不適用</td>
      </tr>
  </tbody>
</table>
<h3 id="windows-特定實作">Windows 特定實作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">gethostname_windows</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    Windows 版本的 gethostname。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    使用 kernel32.GetComputerNameA。
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;This function is Windows-only&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">kernel32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="c1"># BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="n">size</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_ulong</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">kernel32</span><span class="o">.</span><span class="n">GetComputerNameA</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;GetComputerNameA failed&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="k">def</span> <span class="nf">getpid_windows</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="s2">    Windows 版本的 getpid。
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">    使用 kernel32.GetCurrentProcessId。
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;This function is Windows-only&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">kernel32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="c1"># DWORD GetCurrentProcessId(void)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_ulong</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="k">return</span> <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="p">()</span></span></span></code></pre></div><h3 id="跨平台封裝">跨平台封裝</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">get_hostname</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;跨平台取得主機名稱。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="k">return</span> <span class="n">gethostname_windows</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">return</span> <span class="n">gethostname_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">def</span> <span class="nf">get_process_id</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="s2">&#34;&#34;&#34;跨平台取得 process ID。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="k">return</span> <span class="n">getpid_windows</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="k">return</span> <span class="n">getpid_ctypes</span><span class="p">()</span></span></span></code></pre></div><h2 id="錯誤處理與安全性">錯誤處理與安全性</h2>
<h3 id="常見錯誤類型">常見錯誤類型</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">errno</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">safe_gethostname</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    安全版本的 gethostname，包含完整的錯誤處理。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1"># 設定函式簽名</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1"># 驗證參數</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="n">max_len</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&#34;max_len must be positive&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">if</span> <span class="n">max_len</span> <span class="o">&gt;</span> <span class="mi">1024</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&#34;max_len too large (max 1024)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># 建立緩衝區</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1"># 呼叫系統函式</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="c1"># 取得錯誤碼</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">err</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">get_errno</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">if</span> <span class="n">err</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENAMETOOLONG</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">ENAMETOOLONG</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                         <span class="s2">&#34;Hostname too long for buffer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">elif</span> <span class="n">err</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EFAULT</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EFAULT</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">                         <span class="s2">&#34;Invalid buffer address&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;gethostname failed: </span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">errorcode</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="s1">&#39;Unknown&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="c1"># 解碼並處理可能的編碼錯誤</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">        <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;latin-1&#39;</span><span class="p">)</span></span></span></code></pre></div><h3 id="安全性考量">安全性考量</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">使用 ctypes 時的安全性注意事項：
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">1. 緩衝區溢位
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">   - 永遠確保緩衝區大小足夠
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">   - 使用 create_string_buffer() 而非直接操作指標
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">2. 型別安全
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">   - 務必設定 argtypes 和 restype
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">   - 錯誤的型別可能導致程式崩潰或安全漏洞
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">3. 記憶體管理
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">   - ctypes 物件由 Python GC 管理
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">   - 小心回呼函式的生命週期
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">4. 輸入驗證
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">   - 永遠驗證使用者輸入
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">   - 不要直接將未驗證的資料傳給 C 函式
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="k">def</span> <span class="nf">secure_strlen</span><span class="p">(</span><span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    安全的 strlen 範例，包含輸入驗證。
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="c1"># 輸入驗證</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">&#34;Expected str, got {type(s).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c1"># 限制長度避免 DoS</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">MAX_LENGTH</span> <span class="o">=</span> <span class="mi">10_000_000</span>  <span class="c1"># 10 MB</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">MAX_LENGTH</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;String too long (max </span><span class="si">{</span><span class="n">MAX_LENGTH</span><span class="si">}</span><span class="s2"> bytes)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="c1"># 轉換為 bytes</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">encoded</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span></span></span></code></pre></div><h3 id="錯誤碼處理">錯誤碼處理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">errno</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">get_errno_message</span><span class="p">(</span><span class="n">err</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;取得錯誤碼對應的訊息。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1"># char *strerror(int errnum)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">if</span> <span class="n">result</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">return</span> <span class="sa">f</span><span class="s2">&#34;Unknown error </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># 使用範例</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ENOENT (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;EACCES (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">EACCES</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EACCES</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;EINVAL (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h2 id="效能比較ctypes-vs-subprocess">效能比較：ctypes vs subprocess</h2>
<h3 id="測試腳本">測試腳本</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">subprocess</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行效能測試並回傳統計資料。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1"># 暖機</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1"># 實際測試</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="s1">&#39;mean&#39;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>  <span class="c1"># 轉換為微秒</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="s1">&#39;stdev&#39;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s1">&#39;min&#39;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="s1">&#39;max&#39;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="c1"># 方法 1：ctypes</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_ctypes</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="k">return</span> <span class="n">gethostname_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"># 方法 2：subprocess</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_subprocess</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">run</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="p">[</span><span class="s1">&#39;hostname&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="n">capture_output</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="n">text</span><span class="o">=</span><span class="kc">True</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="c1"># 方法 3：Python 標準庫</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_stdlib</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="k">return</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">
</span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="c1"># 執行測試</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;取得主機名稱效能比較&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">
</span></span><span class="line"><span class="ln">52</span><span class="cl">    <span class="n">methods</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;ctypes&#34;</span><span class="p">,</span> <span class="n">hostname_ctypes</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;subprocess&#34;</span><span class="p">,</span> <span class="n">hostname_subprocess</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;socket (stdlib)&#34;</span><span class="p">,</span> <span class="n">hostname_stdlib</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">
</span></span><span class="line"><span class="ln">58</span><span class="cl">    <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span> <span class="ow">in</span> <span class="n">methods</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  平均: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  標準差: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  最小: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;min&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  最大: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;max&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="效能測試結果">效能測試結果</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">取得主機名稱效能比較
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">ctypes:
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  平均: 1.52 us
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  標準差: 0.31 us
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  最小: 1.21 us
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  最大: 8.45 us
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">subprocess:
</span></span><span class="line"><span class="ln">12</span><span class="cl">  平均: 4523.67 us
</span></span><span class="line"><span class="ln">13</span><span class="cl">  標準差: 892.34 us
</span></span><span class="line"><span class="ln">14</span><span class="cl">  最小: 3128.45 us
</span></span><span class="line"><span class="ln">15</span><span class="cl">  最大: 12456.78 us
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">socket (stdlib):
</span></span><span class="line"><span class="ln">18</span><span class="cl">  平均: 0.89 us
</span></span><span class="line"><span class="ln">19</span><span class="cl">  標準差: 0.18 us
</span></span><span class="line"><span class="ln">20</span><span class="cl">  最小: 0.72 us
</span></span><span class="line"><span class="ln">21</span><span class="cl">  最大: 4.23 us</span></span></code></pre></div><h3 id="結果分析">結果分析</h3>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>平均時間</th>
          <th>相對 ctypes</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>socket (stdlib)</strong></td>
          <td>~0.9 us</td>
          <td>0.6x (最快)</td>
          <td>首選，已有封裝</td>
      </tr>
      <tr>
          <td><strong>ctypes</strong></td>
          <td>~1.5 us</td>
          <td>1x (基準)</td>
          <td>無標準庫支援時</td>
      </tr>
      <tr>
          <td><strong>subprocess</strong></td>
          <td>~4500 us</td>
          <td>~3000x (最慢)</td>
          <td>需要執行外部命令時</td>
      </tr>
  </tbody>
</table>
<p><strong>結論</strong>：</p>
<ol>
<li><strong>優先使用標準庫</strong>：如果 Python 標準庫有對應功能，通常是最佳選擇</li>
<li><strong>ctypes 是好的替代方案</strong>：效能接近標準庫，適合未封裝的系統 API</li>
<li><strong>避免 subprocess 取得簡單資訊</strong>：進程建立開銷約 3000 倍</li>
</ol>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>ctypes</th>
          <th>subprocess</th>
          <th>標準庫</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>效能</strong></td>
          <td>優秀 (~1-5 us)</td>
          <td>差 (~3-5 ms)</td>
          <td>最佳 (~1 us)</td>
      </tr>
      <tr>
          <td><strong>可移植性</strong></td>
          <td>需處理平台差異</td>
          <td>取決於命令可用性</td>
          <td>優秀</td>
      </tr>
      <tr>
          <td><strong>複雜度</strong></td>
          <td>中（需了解 C 型別）</td>
          <td>低</td>
          <td>低</td>
      </tr>
      <tr>
          <td><strong>安全性</strong></td>
          <td>需謹慎處理</td>
          <td>需防止命令注入</td>
          <td>良好</td>
      </tr>
      <tr>
          <td><strong>功能範圍</strong></td>
          <td>廣（任何 C 函式）</td>
          <td>廣（任何命令）</td>
          <td>受限於已實作功能</td>
      </tr>
  </tbody>
</table>
<h2 id="實際應用建議">實際應用建議</h2>
<h3 id="何時使用-ctypes">何時使用 ctypes</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">適合使用 ctypes 的情況：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── Python 標準庫沒有對應功能
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── 需要呼叫特定平台的 API
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 效能是關鍵考量
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 需要與 C 函式庫整合
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── 希望避免編譯步驟（相比 Cython）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">不建議使用 ctypes 的情況：
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── 標準庫已有對應功能
</span></span><span class="line"><span class="ln">10</span><span class="cl">├── 大量複雜的 C 介面（考慮 cffi 或 Cython）
</span></span><span class="line"><span class="ln">11</span><span class="cl">├── 需要頻繁傳遞大量資料（考慮 NumPy）
</span></span><span class="line"><span class="ln">12</span><span class="cl">└── 團隊不熟悉 C 語言</span></span></code></pre></div><h3 id="最佳實踐">最佳實踐</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">ctypes 呼叫系統 API 的最佳實踐：
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">1. 封裝成模組
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">   - 將 ctypes 呼叫封裝在獨立模組中
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">   - 提供清晰的 Python API
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">2. 完整的型別宣告
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">   - 永遠設定 argtypes 和 restype
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">   - 使用適當的 ctypes 型別
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">3. 錯誤處理
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">   - 檢查回傳值
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">   - 處理 errno
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">   - 提供有意義的錯誤訊息
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">4. 跨平台支援
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">   - 使用 ctypes.util.find_library()
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">   - 提供平台特定的實作
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">   - 考慮使用 Python 標準庫作為 fallback
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">5. 文件與測試
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">   - 記錄 C 函式的原型
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">   - 與 Python 標準庫比較結果
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">   - 包含效能測試
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span></span></span></code></pre></div><h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>使用 ctypes 實作以下功能：</p>
<ol>
<li><strong>取得環境變數</strong>：呼叫 <code>getenv()</code> 函式</li>
<li><strong>設定環境變數</strong>：呼叫 <code>setenv()</code> 或 <code>putenv()</code> 函式（Unix）</li>
<li><strong>取得當前工作目錄</strong>：呼叫 <code>getcwd()</code> 函式</li>
</ol>
<p>提示：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># getenv 範例框架</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">getenv_ctypes</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="s2">&#34;&#34;&#34;使用 ctypes 取得環境變數。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="c1"># char *getenv(const char *name)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1"># 完成實作...</span></span></span></code></pre></div><h3 id="進階練習">進階練習</h3>
<ol>
<li>
<p>實作一個跨平台的系統資訊模組，包含：</p>
<ul>
<li>主機名稱</li>
<li>Process ID</li>
<li>使用者 ID（Unix）/ 使用者名稱（Windows）</li>
<li>系統時間</li>
</ul>
</li>
<li>
<p>比較你的實作與 <code>psutil</code> 套件的效能差異。</p>
</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://docs.python.org/3/library/ctypes.html">Python ctypes 官方文件</a></li>
<li><a href="https://man7.org/linux/man-pages/dir_section_2.html">Linux man pages - section 2 (system calls)</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/api/">Windows API Reference</a></li>
<li><a href="https://pubs.opengroup.org/onlinepubs/9699919799/">POSIX 標準</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>案例：pybind11 綁定 C++ 類別</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/pybind11-cpp-binding/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/pybind11-cpp-binding/</guid><description>&lt;p>本案例展示如何使用 pybind11 將 C++ 類別完整綁定到 Python，包含建構子、方法、屬性、運算子重載，以及記憶體管理與生命週期控制。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&amp;#43;&amp;#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&amp;#43;&amp;#43; 的綁定">4.3 pybind11：現代 C++ 綁定&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="使用情境">使用情境&lt;/h3>
&lt;p>在以下情境中，你可能需要在 Python 中使用 C++ 類別：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>複用現有 C++ 程式庫&lt;/strong>：公司有成熟的 C++ 資料結構或演算法，想在 Python 專案中使用&lt;/li>
&lt;li>&lt;strong>效能敏感的資料處理&lt;/strong>：需要高效的記憶體管理和計算效能&lt;/li>
&lt;li>&lt;strong>自訂資料結構&lt;/strong>：標準 Python 容器無法滿足特定需求&lt;/li>
&lt;/ol>
&lt;h3 id="設計目標">設計目標&lt;/h3>
&lt;p>本案例將建立一個 &lt;code>StringProcessor&lt;/code> 類別，展示：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">StringProcessor 功能：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── 建構子：支援預設和參數化初始化
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── 方法：字串處理（大小寫轉換、統計、搜尋）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 屬性：可讀寫的狀態屬性
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├── 運算子重載：+ 運算子串接、[] 索引存取
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">├── 記憶體管理：正確處理物件生命週期
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└── 效能優化：避免不必要的記憶體複製&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="實作步驟">實作步驟&lt;/h2>
&lt;h3 id="步驟-1專案結構">步驟 1：專案結構&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">pybind11_string_processor/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">├── setup.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">├── src/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">│ ├── string_processor.hpp # C++ 標頭檔
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">│ ├── string_processor.cpp # C++ 實作
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">│ └── bindings.cpp # pybind11 綁定
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">├── tests/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">│ └── test_string_processor.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">└── benchmark.py&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-2c-類別定義">步驟 2：C++ 類別定義&lt;/h3>
&lt;p>首先，建立 C++ 類別的標頭檔：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// src/string_processor.hpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#ifndef STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">#define STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 10&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 11&lt;/span>&lt;span class="cl">&lt;span class="cm">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 12&lt;/span>&lt;span class="cl">&lt;span class="cm"> * StringProcessor: 高效能字串處理類別
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 13&lt;/span>&lt;span class="cl">&lt;span class="cm"> *
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 14&lt;/span>&lt;span class="cl">&lt;span class="cm"> * 提供字串操作、統計分析和搜尋功能。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 15&lt;/span>&lt;span class="cl">&lt;span class="cm"> * 設計用於展示 pybind11 的類別綁定特性。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 16&lt;/span>&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 17&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">StringProcessor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 18&lt;/span>&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 19&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 20&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 建構子與解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 21&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 22&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 23&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 預設建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 24&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 26&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 參數化建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 27&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">explicit&lt;/span> &lt;span class="nf">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 29&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 複製建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 30&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 32&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 移動建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 33&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 35&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 36&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 37&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 38&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 39&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 基本方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 40&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 41&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 42&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 43&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 44&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 45&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 設定內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 46&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">set_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 47&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 48&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得長度
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 49&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 50&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 51&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否為空
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 52&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">empty&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 53&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 54&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 55&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 字串處理方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 56&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 57&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 58&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 轉換為大寫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 59&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">to_upper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 60&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 61&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 轉換為小寫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 62&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">to_lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 63&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 64&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 反轉字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 65&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">reverse&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 66&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 67&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 移除前後空白
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 68&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">trim&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 69&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 70&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 分割字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 71&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">delimiter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 72&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 73&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取代子字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 74&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 75&lt;/span>&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 76&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 77&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 78&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 統計分析方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 79&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 80&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 81&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 字元頻率統計
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 82&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">char_frequency&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 83&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 84&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 單字計數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 85&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">word_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 86&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 87&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 子字串出現次數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 88&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">count_occurrences&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 89&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 90&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 91&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 搜尋方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 92&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 93&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 94&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 搜尋子字串位置（找不到回傳 -1）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 95&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 96&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 97&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 搜尋所有出現位置
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 98&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 99&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">100&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否包含子字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">101&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">contains&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">102&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">103&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否以指定字串開頭
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">104&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">starts_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">105&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">106&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否以指定字串結尾
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">107&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">ends_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">108&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">109&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">110&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 運算子重載
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">111&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">112&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">113&lt;/span>&lt;span class="cl"> &lt;span class="c1">// + 運算子：串接
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">114&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">115&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">116&lt;/span>&lt;span class="cl"> &lt;span class="c1">// += 運算子：原地串接
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">117&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">118&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">119&lt;/span>&lt;span class="cl"> &lt;span class="c1">// [] 運算子：索引存取
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">120&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="p">[](&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">121&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">122&lt;/span>&lt;span class="cl"> &lt;span class="c1">// == 運算子：相等比較
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">123&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">124&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">125&lt;/span>&lt;span class="cl"> &lt;span class="c1">// != 運算子：不等比較
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">126&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">!=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">127&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">128&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">129&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 指派運算子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">130&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">131&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">132&lt;/span>&lt;span class="cl"> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">133&lt;/span>&lt;span class="cl"> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">134&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">135&lt;/span>&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">136&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">137&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">138&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 處理計數器（用於展示狀態追蹤）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">139&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">mutable&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">140&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">141&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 輔助方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">142&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">increment_operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">operation_count_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">143&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">144&lt;/span>&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">145&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得操作計數（用於效能分析）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">146&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">147&lt;/span>&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">reset_operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">148&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">149&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">150&lt;/span>&lt;span class="cl">&lt;span class="cp">#endif &lt;/span>&lt;span class="c1">// STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-3c-實作">步驟 3：C++ 實作&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// src/string_processor.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;string_processor.hpp&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;algorithm&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cctype&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1">// 建構子與解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 10&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 11&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 13&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 14&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 16&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 17&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 19&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 20&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">)),&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 21&lt;/span>&lt;span class="cl"> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 22&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 24&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::~&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 26&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 27&lt;/span>&lt;span class="cl">&lt;span class="c1">// 基本方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 28&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 29&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 30&lt;/span>&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">set_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 31&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 32&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 33&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 35&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 36&lt;/span>&lt;span class="cl">&lt;span class="c1">// 字串處理方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 37&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 38&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 39&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_upper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 40&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 41&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 42&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 43&lt;/span>&lt;span class="cl"> &lt;span class="p">[](&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">toupper&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 44&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 45&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 46&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 47&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 48&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 49&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 50&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 51&lt;/span>&lt;span class="cl"> &lt;span class="p">[](&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">tolower&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 52&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 53&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 54&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 55&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">reverse&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 56&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 57&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 58&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">reverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 59&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 60&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 61&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 62&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">trim&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 63&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 64&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find_first_not_of&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; &lt;/span>&lt;span class="se">\t\n\r\f\v&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 65&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 66&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 67&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 68&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find_last_not_of&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; &lt;/span>&lt;span class="se">\t\n\r\f\v&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 69&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 70&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 71&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 72&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">delimiter&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 73&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 74&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 75&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 76&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 77&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 空分隔符：按字元分割
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 78&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">char&lt;/span> &lt;span class="nl">c&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 79&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 80&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 81&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 82&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 83&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 84&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 85&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 86&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 87&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">end&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 88&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 89&lt;/span>&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">delimiter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 90&lt;/span>&lt;span class="cl"> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 91&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 92&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 93&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 94&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 95&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 96&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 97&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 98&lt;/span>&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 99&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">100&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">old_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">101&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">102&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">103&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">104&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">105&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">106&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">107&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">108&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">109&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">110&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">111&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">112&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">113&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">114&lt;/span>&lt;span class="cl">&lt;span class="c1">// 統計分析方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">115&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">116&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">117&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">char_frequency&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">118&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">119&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">freq&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">120&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">char&lt;/span> &lt;span class="nl">c&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">121&lt;/span>&lt;span class="cl"> &lt;span class="n">freq&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">122&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">123&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">freq&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">124&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">125&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">126&lt;/span>&lt;span class="cl">&lt;span class="n">size_t&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">word_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">127&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">128&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">129&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">130&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">131&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">132&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">istringstream&lt;/span> &lt;span class="n">iss&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">133&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">134&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">word&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">135&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">iss&lt;/span> &lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">word&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">136&lt;/span>&lt;span class="cl"> &lt;span class="n">count&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">137&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">138&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">count&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">139&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">140&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">141&lt;/span>&lt;span class="cl">&lt;span class="n">size_t&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">count_occurrences&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">142&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">143&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">144&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">145&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">146&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">147&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">148&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">149&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">150&lt;/span>&lt;span class="cl"> &lt;span class="n">count&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">151&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">152&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">153&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">count&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">154&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">155&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">156&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">157&lt;/span>&lt;span class="cl">&lt;span class="c1">// 搜尋方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">158&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">159&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">160&lt;/span>&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">161&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">162&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">163&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">164&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">165&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">166&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">167&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">168&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">169&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">170&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">171&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">172&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">173&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">174&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">175&lt;/span>&lt;span class="cl"> &lt;span class="n">positions&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">176&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">177&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">178&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">179&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">180&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">181&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">contains&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">182&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">183&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">184&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">185&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">186&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">starts_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">187&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">188&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">prefix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">189&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">190&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">191&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compare&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">192&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">193&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">194&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ends_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">195&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">196&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">197&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">198&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">199&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compare&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">200&lt;/span>&lt;span class="cl"> &lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">201&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">202&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">203&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">204&lt;/span>&lt;span class="cl">&lt;span class="c1">// 運算子重載
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">205&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">206&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">207&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">208&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">209&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">210&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">211&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">212&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">213&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">214&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">215&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">216&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">217&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">218&lt;/span>&lt;span class="cl">&lt;span class="kt">char&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="p">[](&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">219&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">220&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">221&lt;/span>&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">out_of_range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Index out of range: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">222&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">223&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">224&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">225&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">226&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">227&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">228&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">229&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">230&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">!=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">231&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">232&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">233&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">234&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">235&lt;/span>&lt;span class="cl">&lt;span class="c1">// 指派運算子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">236&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">237&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">238&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">239&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">this&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">240&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">241&lt;/span>&lt;span class="cl"> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">242&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">243&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">244&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">245&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">246&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">247&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">this&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">248&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">249&lt;/span>&lt;span class="cl"> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">250&lt;/span>&lt;span class="cl"> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">251&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">252&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">253&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-4pybind11-綁定">步驟 4：pybind11 綁定&lt;/h3>
&lt;p>這是最關鍵的部分，將 C++ 類別暴露給 Python：&lt;/p></description><content:encoded><![CDATA[<p>本案例展示如何使用 pybind11 將 C++ 類別完整綁定到 Python，包含建構子、方法、屬性、運算子重載，以及記憶體管理與生命週期控制。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&#43;&#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&#43;&#43; 的綁定">4.3 pybind11：現代 C++ 綁定</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="使用情境">使用情境</h3>
<p>在以下情境中，你可能需要在 Python 中使用 C++ 類別：</p>
<ol>
<li><strong>複用現有 C++ 程式庫</strong>：公司有成熟的 C++ 資料結構或演算法，想在 Python 專案中使用</li>
<li><strong>效能敏感的資料處理</strong>：需要高效的記憶體管理和計算效能</li>
<li><strong>自訂資料結構</strong>：標準 Python 容器無法滿足特定需求</li>
</ol>
<h3 id="設計目標">設計目標</h3>
<p>本案例將建立一個 <code>StringProcessor</code> 類別，展示：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">StringProcessor 功能：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 建構子：支援預設和參數化初始化
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 方法：字串處理（大小寫轉換、統計、搜尋）
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 屬性：可讀寫的狀態屬性
</span></span><span class="line"><span class="ln">5</span><span class="cl">├── 運算子重載：+ 運算子串接、[] 索引存取
</span></span><span class="line"><span class="ln">6</span><span class="cl">├── 記憶體管理：正確處理物件生命週期
</span></span><span class="line"><span class="ln">7</span><span class="cl">└── 效能優化：避免不必要的記憶體複製</span></span></code></pre></div><h2 id="實作步驟">實作步驟</h2>
<h3 id="步驟-1專案結構">步驟 1：專案結構</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">pybind11_string_processor/
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── CMakeLists.txt
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── setup.py
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── src/
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│   ├── string_processor.hpp    # C++ 標頭檔
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│   ├── string_processor.cpp    # C++ 實作
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   └── bindings.cpp            # pybind11 綁定
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">├── tests/
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│   └── test_string_processor.py
</span></span><span class="line"><span class="ln">10</span><span class="cl">└── benchmark.py</span></span></code></pre></div><h3 id="步驟-2c-類別定義">步驟 2：C++ 類別定義</h3>
<p>首先，建立 C++ 類別的標頭檔：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/string_processor.hpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#ifndef STRING_PROCESSOR_HPP
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#define STRING_PROCESSOR_HPP
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;unordered_map&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdexcept&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="cm"> * StringProcessor: 高效能字串處理類別
</span></span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="cm"> * 提供字串操作、統計分析和搜尋功能。
</span></span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="cm"> * 設計用於展示 pybind11 的類別綁定特性。
</span></span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="k">class</span> <span class="nc">StringProcessor</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c1"></span>    <span class="c1">// 建構子與解構子
</span></span></span><span class="line"><span class="ln"> 21</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 22</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">    <span class="c1">// 預設建構子
</span></span></span><span class="line"><span class="ln"> 24</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">    <span class="c1">// 參數化建構子
</span></span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="c1"></span>    <span class="k">explicit</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">    <span class="c1">// 複製建構子
</span></span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">    <span class="c1">// 移動建構子
</span></span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">    <span class="c1">// 解構子
</span></span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c1"></span>    <span class="o">~</span><span class="n">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="c1"></span>    <span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 41</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">    <span class="c1">// 取得內容
</span></span></span><span class="line"><span class="ln"> 43</span><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">    <span class="c1">// 設定內容
</span></span></span><span class="line"><span class="ln"> 46</span><span class="cl"><span class="c1"></span>    <span class="kt">void</span> <span class="nf">set_content</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">    <span class="c1">// 取得長度
</span></span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">length</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">    <span class="c1">// 是否為空
</span></span></span><span class="line"><span class="ln"> 52</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">empty</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="c1"></span>    <span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 57</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">    <span class="c1">// 轉換為大寫
</span></span></span><span class="line"><span class="ln"> 59</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_upper</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">    <span class="c1">// 轉換為小寫
</span></span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_lower</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">    <span class="c1">// 反轉字串
</span></span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">reverse</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="c1">// 移除前後空白
</span></span></span><span class="line"><span class="ln"> 68</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">trim</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">    <span class="c1">// 分割字串
</span></span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">split</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">delimiter</span> <span class="o">=</span> <span class="s">&#34; &#34;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="c1">// 取代子字串
</span></span></span><span class="line"><span class="ln"> 74</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">replace</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">old_str</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">                        <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">new_str</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="c1"></span>    <span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln"> 79</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 80</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="c1">// 字元頻率統計
</span></span></span><span class="line"><span class="ln"> 82</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">char_frequency</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="c1">// 單字計數
</span></span></span><span class="line"><span class="ln"> 85</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">word_count</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="c1">// 子字串出現次數
</span></span></span><span class="line"><span class="ln"> 88</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">count_occurrences</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 91</span><span class="cl"><span class="c1"></span>    <span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln"> 92</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 93</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="c1">// 搜尋子字串位置（找不到回傳 -1）
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="c1"></span>    <span class="kt">int</span> <span class="nf">find</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="c1">// 搜尋所有出現位置
</span></span></span><span class="line"><span class="ln"> 98</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">find_all</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">
</span></span><span class="line"><span class="ln">100</span><span class="cl">    <span class="c1">// 是否包含子字串
</span></span></span><span class="line"><span class="ln">101</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">contains</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">
</span></span><span class="line"><span class="ln">103</span><span class="cl">    <span class="c1">// 是否以指定字串開頭
</span></span></span><span class="line"><span class="ln">104</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">starts_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">prefix</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="c1">// 是否以指定字串結尾
</span></span></span><span class="line"><span class="ln">107</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">ends_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">suffix</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">110</span><span class="cl"><span class="c1"></span>    <span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">112</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">    <span class="c1">// + 運算子：串接
</span></span></span><span class="line"><span class="ln">114</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">
</span></span><span class="line"><span class="ln">116</span><span class="cl">    <span class="c1">// += 運算子：原地串接
</span></span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">
</span></span><span class="line"><span class="ln">119</span><span class="cl">    <span class="c1">// [] 運算子：索引存取
</span></span></span><span class="line"><span class="ln">120</span><span class="cl"><span class="c1"></span>    <span class="kt">char</span> <span class="k">operator</span><span class="p">[](</span><span class="n">size_t</span> <span class="n">index</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">
</span></span><span class="line"><span class="ln">122</span><span class="cl">    <span class="c1">// == 運算子：相等比較
</span></span></span><span class="line"><span class="ln">123</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">    <span class="c1">// != 運算子：不等比較
</span></span></span><span class="line"><span class="ln">126</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">
</span></span><span class="line"><span class="ln">128</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">129</span><span class="cl"><span class="c1"></span>    <span class="c1">// 指派運算子
</span></span></span><span class="line"><span class="ln">130</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">131</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">
</span></span><span class="line"><span class="ln">135</span><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="c1">// 處理計數器（用於展示狀態追蹤）
</span></span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="c1"></span>    <span class="k">mutable</span> <span class="n">size_t</span> <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="c1">// 輔助方法
</span></span></span><span class="line"><span class="ln">142</span><span class="cl"><span class="c1"></span>    <span class="kt">void</span> <span class="nf">increment_operation_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="o">++</span><span class="n">operation_count_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">
</span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">    <span class="c1">// 取得操作計數（用於效能分析）
</span></span></span><span class="line"><span class="ln">146</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="n">operation_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">operation_count_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">147</span><span class="cl">    <span class="kt">void</span> <span class="nf">reset_operation_count</span><span class="p">()</span> <span class="p">{</span> <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">
</span></span><span class="line"><span class="ln">150</span><span class="cl"><span class="cp">#endif </span><span class="c1">// STRING_PROCESSOR_HPP
</span></span></span></code></pre></div><h3 id="步驟-3c-實作">步驟 3：C++ 實作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/string_processor.cpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&#34;string_processor.hpp&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cctype&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sstream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="c1">// 建構子與解構子
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">()</span> <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">
</span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">),</span> <span class="n">operation_count_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">
</span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span>
</span></span><span class="line"><span class="ln"> 20</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">)),</span> <span class="n">operation_count_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">
</span></span><span class="line"><span class="ln"> 24</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::~</span><span class="n">StringProcessor</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">
</span></span><span class="line"><span class="ln"> 26</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 28</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="kt">void</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">set_content</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">    <span class="n">content_</span> <span class="o">=</span> <span class="n">content</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">
</span></span><span class="line"><span class="ln"> 35</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_upper</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">                   <span class="p">[](</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">toupper</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">
</span></span><span class="line"><span class="ln"> 47</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_lower</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">                   <span class="p">[](</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">tolower</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">
</span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">reverse</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">reverse</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">
</span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">trim</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">    <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find_first_not_of</span><span class="p">(</span><span class="s">&#34; </span><span class="se">\t\n\r\f\v</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">        <span class="k">return</span> <span class="s">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">    <span class="n">size_t</span> <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find_last_not_of</span><span class="p">(</span><span class="s">&#34; </span><span class="se">\t\n\r\f\v</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">
</span></span><span class="line"><span class="ln"> 72</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">split</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">delimiter</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">delimiter</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="c1">// 空分隔符：按字元分割
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="c1"></span>        <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">content_</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">            <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">    <span class="n">size_t</span> <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">delimiter</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">end</span> <span class="o">+</span> <span class="n">delimiter</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">delimiter</span><span class="p">,</span> <span class="n">start</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">    <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">
</span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">replace</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">old_str</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">                                     <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">new_str</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">old_str</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="k">return</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">old_str</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">        <span class="n">result</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">old_str</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">new_str</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">new_str</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">
</span></span><span class="line"><span class="ln">113</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">114</span><span class="cl"><span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln">115</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">116</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">char_frequency</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">freq</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">content_</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">        <span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">    <span class="k">return</span> <span class="n">freq</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl"><span class="n">size_t</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">word_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">
</span></span><span class="line"><span class="ln">132</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">istringstream</span> <span class="n">iss</span><span class="p">(</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">    <span class="n">size_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">word</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">iss</span> <span class="o">&gt;&gt;</span> <span class="n">word</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">        <span class="n">count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="k">return</span> <span class="n">count</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="n">size_t</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">count_occurrences</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">substring</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">144</span><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">146</span><span class="cl">
</span></span><span class="line"><span class="ln">147</span><span class="cl">    <span class="n">size_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">150</span><span class="cl">        <span class="n">count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">151</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">substring</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">152</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">153</span><span class="cl">    <span class="k">return</span> <span class="n">count</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">154</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">155</span><span class="cl">
</span></span><span class="line"><span class="ln">156</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">157</span><span class="cl"><span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln">158</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">159</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">160</span><span class="cl"><span class="kt">int</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">start</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">162</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">163</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">pos</span> <span class="o">==</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="o">?</span> <span class="o">-</span><span class="mi">1</span> <span class="o">:</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">164</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">
</span></span><span class="line"><span class="ln">166</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">find_all</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">167</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">169</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">substring</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">        <span class="k">return</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">171</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">172</span><span class="cl">
</span></span><span class="line"><span class="ln">173</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">174</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">175</span><span class="cl">        <span class="n">positions</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">176</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">substring</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">177</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">178</span><span class="cl">    <span class="k">return</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">
</span></span><span class="line"><span class="ln">181</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">184</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">185</span><span class="cl">
</span></span><span class="line"><span class="ln">186</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">starts_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">prefix</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">187</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">188</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">prefix</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">189</span><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">190</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">191</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">compare</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">prefix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">prefix</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">193</span><span class="cl">
</span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">ends_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">suffix</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">198</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">199</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">compare</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">-</span> <span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">                            <span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">suffix</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">202</span><span class="cl">
</span></span><span class="line"><span class="ln">203</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">204</span><span class="cl"><span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">205</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">206</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">207</span><span class="cl"><span class="n">StringProcessor</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">208</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">209</span><span class="cl">    <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">content_</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">210</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">211</span><span class="cl">
</span></span><span class="line"><span class="ln">212</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">213</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">214</span><span class="cl">    <span class="n">content_</span> <span class="o">+=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">215</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">216</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">217</span><span class="cl">
</span></span><span class="line"><span class="ln">218</span><span class="cl"><span class="kt">char</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="p">[](</span><span class="n">size_t</span> <span class="n">index</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">219</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">220</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">221</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">out_of_range</span><span class="p">(</span><span class="s">&#34;Index out of range: &#34;</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">index</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">222</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">223</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">224</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">225</span><span class="cl">
</span></span><span class="line"><span class="ln">226</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">227</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">228</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">229</span><span class="cl">
</span></span><span class="line"><span class="ln">230</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">231</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span> <span class="o">!=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">232</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">233</span><span class="cl">
</span></span><span class="line"><span class="ln">234</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">235</span><span class="cl"><span class="c1">// 指派運算子
</span></span></span><span class="line"><span class="ln">236</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">237</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">238</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">239</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">this</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">240</span><span class="cl">        <span class="n">content_</span> <span class="o">=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">241</span><span class="cl">        <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">242</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">243</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">244</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">245</span><span class="cl">
</span></span><span class="line"><span class="ln">246</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">247</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">this</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">248</span><span class="cl">        <span class="n">content_</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">249</span><span class="cl">        <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">250</span><span class="cl">        <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">251</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">252</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">253</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="步驟-4pybind11-綁定">步驟 4：pybind11 綁定</h3>
<p>這是最關鍵的部分，將 C++ 類別暴露給 Python：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/bindings.cpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/stl.h&gt;</span><span class="cp">  </span><span class="c1">// 支援 STL 容器自動轉換
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;pybind11/operators.h&gt;</span><span class="cp">  </span><span class="c1">// 支援運算子重載
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;string_processor.hpp&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">  9</span><span class="cl">
</span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">string_processor</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">doc</span><span class="p">()</span> <span class="o">=</span> <span class="s">&#34;StringProcessor: 高效能字串處理模組&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="c1"></span>    <span class="c1">// 類別綁定
</span></span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="c1"></span>    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="c1"></span>        <span class="c1">// 建構子
</span></span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;&gt;</span><span class="p">(),</span> <span class="s">&#34;建立空的 StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;&gt;</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;content&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">             <span class="s">&#34;使用指定內容建立 StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">        <span class="c1">// 複製建構（Python 的 copy 模組會使用）
</span></span></span><span class="line"><span class="ln"> 26</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;&gt;</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="c1"></span>        <span class="c1">// 屬性
</span></span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 31</span><span class="cl"><span class="c1"></span>        <span class="c1">// content 屬性：可讀寫
</span></span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def_property</span><span class="p">(</span><span class="s">&#34;content&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">                      <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">                      <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">set_content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">                      <span class="s">&#34;字串內容&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">        <span class="c1">// 唯讀屬性
</span></span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;length&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">length</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">                               <span class="s">&#34;字串長度&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;empty&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">empty</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">                               <span class="s">&#34;是否為空&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;operation_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">operation_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">                               <span class="s">&#34;操作計數器&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="c1"></span>        <span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 50</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 51</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;reset_operation_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">reset_operation_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">             <span class="s">&#34;重置操作計數器&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="c1"></span>        <span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 57</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 58</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;to_upper&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_upper</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">             <span class="s">&#34;轉換為大寫&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;to_lower&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_lower</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">             <span class="s">&#34;轉換為小寫&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;reverse&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">reverse</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">             <span class="s">&#34;反轉字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;trim&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">trim</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">             <span class="s">&#34;移除前後空白&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;split&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">split</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;delimiter&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34; &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">             <span class="s">&#34;以分隔符分割字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;replace&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">replace</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;old_str&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;new_str&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">             <span class="s">&#34;取代子字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 81</span><span class="cl"><span class="c1"></span>        <span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln"> 82</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 83</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;char_frequency&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">char_frequency</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">             <span class="s">&#34;統計字元頻率&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;word_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">word_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">             <span class="s">&#34;計算單字數量&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;count_occurrences&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">count_occurrences</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">             <span class="s">&#34;計算子字串出現次數&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="c1"></span>        <span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln"> 96</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;find&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">find</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;start&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">             <span class="s">&#34;搜尋子字串位置（找不到回傳 -1）&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;find_all&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">find_all</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">             <span class="s">&#34;搜尋所有出現位置&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">106</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;contains&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">             <span class="s">&#34;是否包含子字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;starts_with&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">starts_with</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;prefix&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">             <span class="s">&#34;是否以指定字串開頭&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">114</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;ends_with&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">ends_with</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;suffix&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">             <span class="s">&#34;是否以指定字串結尾&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">
</span></span><span class="line"><span class="ln">119</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">120</span><span class="cl"><span class="c1"></span>        <span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">121</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">122</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">        <span class="c1">// + 運算子：StringProcessor + StringProcessor
</span></span></span><span class="line"><span class="ln">124</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">+</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="c1">// += 運算子
</span></span></span><span class="line"><span class="ln">127</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">+=</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="c1">// == 和 != 運算子
</span></span></span><span class="line"><span class="ln">130</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">==</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">!=</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">
</span></span><span class="line"><span class="ln">133</span><span class="cl">        <span class="c1">// [] 運算子：索引存取
</span></span></span><span class="line"><span class="ln">134</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__getitem__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="p">[],</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;index&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">             <span class="s">&#34;取得指定位置的字元&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">
</span></span><span class="line"><span class="ln">139</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">140</span><span class="cl"><span class="c1"></span>        <span class="c1">// Python 特殊方法
</span></span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">142</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">        <span class="c1">// __repr__：物件表示
</span></span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__repr__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">146</span><span class="cl">                 <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">repr</span> <span class="o">=</span> <span class="s">&#34;&lt;StringProcessor content=&#39;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">147</span><span class="cl">                 <span class="k">if</span> <span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">50</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl">                     <span class="n">repr</span> <span class="o">+=</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">47</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#34;...&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">                 <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">150</span><span class="cl">                     <span class="n">repr</span> <span class="o">+=</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">151</span><span class="cl">                 <span class="p">}</span>
</span></span><span class="line"><span class="ln">152</span><span class="cl">                 <span class="n">repr</span> <span class="o">+=</span> <span class="s">&#34;&#39; length=&#34;</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="o">+</span> <span class="s">&#34;&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">153</span><span class="cl">                 <span class="k">return</span> <span class="n">repr</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">154</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">155</span><span class="cl">
</span></span><span class="line"><span class="ln">156</span><span class="cl">        <span class="c1">// __str__：字串轉換
</span></span></span><span class="line"><span class="ln">157</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__str__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">158</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">159</span><span class="cl">                 <span class="k">return</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">160</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">
</span></span><span class="line"><span class="ln">162</span><span class="cl">        <span class="c1">// __len__：長度
</span></span></span><span class="line"><span class="ln">163</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__len__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">164</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">length</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">
</span></span><span class="line"><span class="ln">166</span><span class="cl">        <span class="c1">// __bool__：布林轉換
</span></span></span><span class="line"><span class="ln">167</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__bool__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">169</span><span class="cl">                 <span class="k">return</span> <span class="o">!</span><span class="n">sp</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">171</span><span class="cl">
</span></span><span class="line"><span class="ln">172</span><span class="cl">        <span class="c1">// __contains__：in 運算子
</span></span></span><span class="line"><span class="ln">173</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__contains__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">174</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">175</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">176</span><span class="cl">
</span></span><span class="line"><span class="ln">177</span><span class="cl">        <span class="c1">// __iter__：迭代支援
</span></span></span><span class="line"><span class="ln">178</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__iter__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">                 <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_iterator</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">181</span><span class="cl">                                          <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl">             <span class="p">},</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">keep_alive</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">&gt;</span><span class="p">())</span>  <span class="c1">// 保持物件存活
</span></span></span><span class="line"><span class="ln">184</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">185</span><span class="cl">        <span class="c1">// __hash__：雜湊支援（讓物件可作為 dict key）
</span></span></span><span class="line"><span class="ln">186</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__hash__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">187</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">188</span><span class="cl">                 <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">{}(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">189</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">190</span><span class="cl">
</span></span><span class="line"><span class="ln">191</span><span class="cl">        <span class="c1">// 支援 pickle
</span></span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">pickle</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">193</span><span class="cl">            <span class="c1">// __getstate__
</span></span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="c1"></span>            <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">                <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">            <span class="c1">// __setstate__
</span></span></span><span class="line"><span class="ln">198</span><span class="cl"><span class="c1"></span>            <span class="p">[](</span><span class="n">py</span><span class="o">::</span><span class="n">tuple</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">199</span><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">                    <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">&#34;Invalid state&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="ln">202</span><span class="cl">                <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">cast</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">203</span><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="ln">204</span><span class="cl">        <span class="p">));</span>
</span></span><span class="line"><span class="ln">205</span><span class="cl">
</span></span><span class="line"><span class="ln">206</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">207</span><span class="cl"><span class="c1"></span>    <span class="c1">// 模組層級函式
</span></span></span><span class="line"><span class="ln">208</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">209</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;concatenate&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">210</span><span class="cl">          <span class="p">[](</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;&amp;</span> <span class="n">processors</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">211</span><span class="cl">             <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">separator</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">212</span><span class="cl">              <span class="k">if</span> <span class="p">(</span><span class="n">processors</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">213</span><span class="cl">                  <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">214</span><span class="cl">              <span class="p">}</span>
</span></span><span class="line"><span class="ln">215</span><span class="cl">              <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">processors</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">216</span><span class="cl">              <span class="k">for</span> <span class="p">(</span><span class="n">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">processors</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">217</span><span class="cl">                  <span class="n">result</span> <span class="o">+=</span> <span class="n">separator</span> <span class="o">+</span> <span class="n">processors</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">218</span><span class="cl">              <span class="p">}</span>
</span></span><span class="line"><span class="ln">219</span><span class="cl">              <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">220</span><span class="cl">          <span class="p">},</span>
</span></span><span class="line"><span class="ln">221</span><span class="cl">          <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;processors&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">222</span><span class="cl">          <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;separator&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">223</span><span class="cl">          <span class="s">&#34;串接多個 StringProcessor&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">224</span><span class="cl">
</span></span><span class="line"><span class="ln">225</span><span class="cl">    <span class="c1">// 版本資訊
</span></span></span><span class="line"><span class="ln">226</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">attr</span><span class="p">(</span><span class="s">&#34;__version__&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34;0.1.0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">227</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="步驟-5建構檔案">步驟 5：建構檔案</h3>
<p><strong>CMakeLists.txt</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.15</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="err"></span><span class="nb">project</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">LANGUAGES</span> <span class="s">CXX</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="err"></span><span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_CXX_STANDARD</span> <span class="s">17</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="err"></span><span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_CXX_STANDARD_REQUIRED</span> <span class="s">ON</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="err"></span><span class="c"># 找到 pybind11
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c"></span><span class="nb">find_package</span><span class="p">(</span><span class="s">pybind11</span> <span class="s">REQUIRED</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="err"></span><span class="c"># 建立 Python 模組
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c"></span><span class="nb">pybind11_add_module</span><span class="p">(</span><span class="s">string_processor</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="s">src/string_processor.cpp</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="s">src/bindings.cpp</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="err"></span><span class="c"># 包含標頭檔目錄
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c"></span><span class="nb">target_include_directories</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">PRIVATE</span> <span class="s">src</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="err"></span><span class="c"># 優化設定
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c"></span><span class="nb">target_compile_options</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">PRIVATE</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="o">$&lt;</span><span class="nv">$&lt;CXX_COMPILER_ID:GNU,Clang</span><span class="o">&gt;</span><span class="s">:-O3</span> <span class="s">-march=native&gt;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="o">$&lt;</span><span class="nv">$&lt;CXX_COMPILER_ID:MSVC</span><span class="o">&gt;</span><span class="s">:/O2&gt;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>setup.py</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">from</span> <span class="nn">pybind11.setup_helpers</span> <span class="kn">import</span> <span class="n">Pybind11Extension</span><span class="p">,</span> <span class="n">build_ext</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">ext_modules</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">Pybind11Extension</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;string_processor&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="n">sources</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="s2">&#34;src/string_processor.cpp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="s2">&#34;src/bindings.cpp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">include_dirs</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;src&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">cxx_std</span><span class="o">=</span><span class="mi">17</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">extra_compile_args</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;-O3&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">name</span><span class="o">=</span><span class="s2">&#34;string_processor&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">version</span><span class="o">=</span><span class="s2">&#34;0.1.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">description</span><span class="o">=</span><span class="s2">&#34;High-performance string processor using pybind11&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">ext_modules</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">cmdclass</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;build_ext&#34;</span><span class="p">:</span> <span class="n">build_ext</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">python_requires</span><span class="o">=</span><span class="s2">&#34;&gt;=3.8&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><h2 id="記憶體管理與物件生命週期">記憶體管理與物件生命週期</h2>
<h3 id="pybind11-的記憶體管理策略">pybind11 的記憶體管理策略</h3>
<p>pybind11 提供多種方式控制物件的所有權：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// 1. return_value_policy::automatic（預設）
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">// pybind11 自動決定最佳策略
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">// 2. return_value_policy::copy
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 總是建立副本，Python 擁有副本
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_copy&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">copy</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1">// 3. return_value_policy::reference
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">// 回傳參考，不轉移所有權（危險：可能產生懸空指標）
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_ref&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">reference</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1">// 4. return_value_policy::reference_internal
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1">// 回傳參考，並保持父物件存活
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_internal&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">reference_internal</span><span class="p">)</span></span></span></code></pre></div><h3 id="keep_alive-策略">keep_alive 策略</h3>
<p>當物件間有依賴關係時，使用 <code>keep_alive</code> 確保生命週期正確：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// keep_alive&lt;Nurse, Patient&gt;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">// Nurse: 需要被保持存活的物件的引數索引
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// Patient: 依賴 Nurse 的物件的引數索引
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1">// 0 = 回傳值, 1 = self, 2+ = 其他引數
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 範例：迭代器需要保持原物件存活
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__iter__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">     <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">         <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_iterator</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">                                  <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">     <span class="p">},</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">keep_alive</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">&gt;</span><span class="p">())</span>  <span class="c1">// 回傳值(0)存活期間，self(1)必須存活
</span></span></span></code></pre></div><h3 id="智慧指標支援">智慧指標支援</h3>
<p>pybind11 自動支援 <code>std::shared_ptr</code> 和 <code>std::unique_ptr</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// 使用 shared_ptr 管理物件
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1">// 工廠函式回傳 shared_ptr
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"></span><span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;create_processor&#34;</span><span class="p">,</span> <span class="p">[]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;</span><span class="p">(</span><span class="s">&#34;factory created&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">});</span></span></span></code></pre></div><h2 id="python-使用範例">Python 使用範例</h2>
<h3 id="基本使用">基本使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">string_processor</span> <span class="kn">import</span> <span class="n">StringProcessor</span><span class="p">,</span> <span class="n">concatenate</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 建立物件</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;Hello, World!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>           <span class="c1"># Hello, World!</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">sp</span><span class="p">))</span>     <span class="c1"># &lt;StringProcessor content=&#39;Hello, World!&#39; length=13&gt;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sp</span><span class="p">))</span>      <span class="c1"># 13</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 屬性存取</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># Hello, World!</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">length</span><span class="p">)</span>    <span class="c1"># 13</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">empty</span><span class="p">)</span>     <span class="c1"># False</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 修改內容</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">sp</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s2">&#34;New content&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># New content</span></span></span></code></pre></div><h3 id="字串處理">字串處理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;  Hello, Python World!  &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 大小寫轉換</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">())</span>  <span class="c1"># &#34;  HELLO, PYTHON WORLD!  &#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">())</span>  <span class="c1"># &#34;  hello, python world!  &#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 修剪空白</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">trim</span><span class="p">())</span>      <span class="c1"># &#34;Hello, Python World!&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 反轉</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">())</span>   <span class="c1"># &#34;  !dlroW nohtyP ,olleH  &#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 分割</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;apple,banana,cherry&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34;,&#34;</span><span class="p">))</span>  <span class="c1"># [&#39;apple&#39;, &#39;banana&#39;, &#39;cherry&#39;]</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># 取代</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&#34;,&#34;</span><span class="p">,</span> <span class="s2">&#34; | &#34;</span><span class="p">))</span>  <span class="c1"># &#34;apple | banana | cherry&#34;</span></span></span></code></pre></div><h3 id="統計與搜尋">統計與搜尋</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;hello hello world&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 統計</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">())</span>              <span class="c1"># 3</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span> <span class="c1"># 2</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">())</span>          <span class="c1"># {&#39;h&#39;: 2, &#39;e&#39;: 2, &#39;l&#39;: 5, ...}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 搜尋</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>             <span class="c1"># 12</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span>         <span class="c1"># [0, 6]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>         <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">starts_with</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span>      <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">ends_with</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>        <span class="c1"># True</span></span></span></code></pre></div><h3 id="運算子使用">運算子使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp1</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">sp2</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34; World&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># + 運算子</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">sp3</span> <span class="o">=</span> <span class="n">sp1</span> <span class="o">+</span> <span class="n">sp2</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># &#34;Hello World&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># += 運算子</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">sp1</span> <span class="o">+=</span> <span class="n">sp2</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># &#34;Hello World&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># [] 索引</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>        <span class="c1"># &#39;H&#39;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="p">[</span><span class="mi">6</span><span class="p">])</span>        <span class="c1"># &#39;W&#39;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># in 運算子</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;World&#34;</span> <span class="ow">in</span> <span class="n">sp3</span><span class="p">)</span>  <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 比較運算子</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span> <span class="o">==</span> <span class="n">sp3</span><span class="p">)</span>    <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span> <span class="o">!=</span> <span class="n">sp2</span><span class="p">)</span>    <span class="c1"># True</span></span></span></code></pre></div><h3 id="python-特殊功能">Python 特殊功能</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">copy</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">pickle</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;test data&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 迭代</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">sp</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">char</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span>  <span class="c1"># t e s t   d a t a</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 複製</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">sp_copy</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 序列化</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">sp_restored</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp_restored</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>  <span class="c1"># &#34;test data&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># 作為 dict key</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">cache</span> <span class="o">=</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="s2">&#34;cached value&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">sp</span><span class="p">])</span>  <span class="c1"># &#34;cached value&#34;</span></span></span></code></pre></div><h2 id="效能測試">效能測試</h2>
<p>建立效能測試腳本，比較 C++ 綁定與純 Python 實作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1"># benchmark.py</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="s2">效能比較：pybind11 StringProcessor vs 純 Python
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">  5</span><span class="cl">
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">Any</span>
</span></span><span class="line"><span class="ln">  9</span><span class="cl">
</span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="c1"># pybind11 版本</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="kn">from</span> <span class="nn">string_processor</span> <span class="kn">import</span> <span class="n">StringProcessor</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="c1"># 純 Python 版本</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="k">class</span> <span class="nc">PyStringProcessor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">    <span class="s2">&#34;&#34;&#34;純 Python 實作作為效能基準&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 16</span><span class="cl">
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">content</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">
</span></span><span class="line"><span class="ln"> 20</span><span class="cl">    <span class="nd">@property</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="nd">@content.setter</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">    <span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">value</span>
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">    <span class="k">def</span> <span class="nf">to_upper</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">    <span class="k">def</span> <span class="nf">to_lower</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">    <span class="k">def</span> <span class="nf">reverse</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">    <span class="k">def</span> <span class="nf">split</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">delimiter</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">delimiter</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">    <span class="k">def</span> <span class="nf">char_frequency</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">        <span class="n">freq</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">            <span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">freq</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">        <span class="k">return</span> <span class="n">freq</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">    <span class="k">def</span> <span class="nf">word_count</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="k">def</span> <span class="nf">count_occurrences</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">substring</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">        <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">            <span class="n">pos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">            <span class="k">if</span> <span class="n">pos</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">            <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">            <span class="n">start</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">        <span class="k">return</span> <span class="n">count</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">    <span class="k">def</span> <span class="nf">find_all</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">substring</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">        <span class="n">positions</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">            <span class="n">pos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">            <span class="k">if</span> <span class="n">pos</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">            <span class="n">positions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">            <span class="n">start</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">        <span class="k">return</span> <span class="n">positions</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">
</span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[],</span> <span class="n">Any</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">              <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">              <span class="n">warmup</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行效能測試並回傳統計資料&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">    <span class="c1"># 預熱</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">warmup</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">    <span class="c1"># 正式測試</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>  <span class="c1"># 轉換為毫秒</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="s2">&#34;mean&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="s2">&#34;stdev&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">        <span class="s2">&#34;min&#34;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">        <span class="s2">&#34;max&#34;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">        <span class="s2">&#34;median&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">
</span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="k">def</span> <span class="nf">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">    <span class="s2">&#34;&#34;&#34;產生測試用字串&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="n">base</span> <span class="o">=</span> <span class="s2">&#34;Hello World! This is a test string for benchmarking. &#34;</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">base</span> <span class="o">*</span> <span class="p">(</span><span class="n">size</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">base</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))[:</span><span class="n">size</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">
</span></span><span class="line"><span class="ln">100</span><span class="cl"><span class="k">def</span> <span class="nf">run_benchmarks</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行所有效能測試&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;StringProcessor 效能測試：pybind11 vs 純 Python&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="n">sizes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1_000</span><span class="p">,</span> <span class="mi">10_000</span><span class="p">,</span> <span class="mi">100_000</span><span class="p">,</span> <span class="mi">1_000_000</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">
</span></span><span class="line"><span class="ln">108</span><span class="cl">    <span class="k">for</span> <span class="n">size</span> <span class="ow">in</span> <span class="n">sizes</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">        <span class="n">content</span> <span class="o">=</span> <span class="n">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="n">cpp_sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">        <span class="n">py_sp</span> <span class="o">=</span> <span class="n">PyStringProcessor</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">
</span></span><span class="line"><span class="ln">113</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">--- 字串長度：</span><span class="si">{</span><span class="n">size</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2"> 字元 ---</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">114</span><span class="cl">
</span></span><span class="line"><span class="ln">115</span><span class="cl">        <span class="c1"># 測試項目</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">        <span class="n">tests</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;to_upper&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;to_lower&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;reverse&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;char_frequency&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;word_count&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;count_occurrences&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;test&#34;</span><span class="p">),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;test&#34;</span><span class="p">)),</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;find_all&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">)),</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">cpp_func</span><span class="p">,</span> <span class="n">py_func</span> <span class="ow">in</span> <span class="n">tests</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">            <span class="n">cpp_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cpp_func</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">            <span class="n">py_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">py_func</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">
</span></span><span class="line"><span class="ln">130</span><span class="cl">            <span class="n">speedup</span> <span class="o">=</span> <span class="n">py_result</span><span class="p">[</span><span class="s2">&#34;mean&#34;</span><span class="p">]</span> <span class="o">/</span> <span class="n">cpp_result</span><span class="p">[</span><span class="s2">&#34;mean&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">
</span></span><span class="line"><span class="ln">132</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">name</span><span class="si">:</span><span class="s2">20s</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  C++:    </span><span class="si">{</span><span class="n">cpp_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">8.4f</span><span class="si">}</span><span class="s2"> ms (stdev: </span><span class="si">{</span><span class="n">cpp_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  Python: </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">8.4f</span><span class="si">}</span><span class="s2"> ms (stdev: </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  加速比: </span><span class="si">{</span><span class="n">speedup</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">            <span class="nb">print</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl">
</span></span><span class="line"><span class="ln">140</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="n">run_benchmarks</span><span class="p">()</span></span></span></code></pre></div><h3 id="預期效能結果">預期效能結果</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">======================================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">StringProcessor 效能測試：pybind11 vs 純 Python
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">======================================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">--- 字串長度：1,000 字元 ---
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">to_upper
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  C++:      0.0012 ms (stdev: 0.0003)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  Python:   0.0008 ms (stdev: 0.0002)
</span></span><span class="line"><span class="ln">10</span><span class="cl">  加速比: 0.67x
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">char_frequency
</span></span><span class="line"><span class="ln">13</span><span class="cl">  C++:      0.0089 ms (stdev: 0.0012)
</span></span><span class="line"><span class="ln">14</span><span class="cl">  Python:   0.0423 ms (stdev: 0.0045)
</span></span><span class="line"><span class="ln">15</span><span class="cl">  加速比: 4.75x
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">word_count
</span></span><span class="line"><span class="ln">18</span><span class="cl">  C++:      0.0034 ms (stdev: 0.0008)
</span></span><span class="line"><span class="ln">19</span><span class="cl">  Python:   0.0028 ms (stdev: 0.0006)
</span></span><span class="line"><span class="ln">20</span><span class="cl">  加速比: 0.82x
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">--- 字串長度：100,000 字元 ---
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">to_upper
</span></span><span class="line"><span class="ln">25</span><span class="cl">  C++:      0.0892 ms (stdev: 0.0089)
</span></span><span class="line"><span class="ln">26</span><span class="cl">  Python:   0.0634 ms (stdev: 0.0067)
</span></span><span class="line"><span class="ln">27</span><span class="cl">  加速比: 0.71x
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">char_frequency
</span></span><span class="line"><span class="ln">30</span><span class="cl">  C++:      0.7823 ms (stdev: 0.0456)
</span></span><span class="line"><span class="ln">31</span><span class="cl">  Python:   4.2341 ms (stdev: 0.2134)
</span></span><span class="line"><span class="ln">32</span><span class="cl">  加速比: 5.41x
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl">count_occurrences
</span></span><span class="line"><span class="ln">35</span><span class="cl">  C++:      0.0234 ms (stdev: 0.0034)
</span></span><span class="line"><span class="ln">36</span><span class="cl">  Python:   0.0567 ms (stdev: 0.0078)
</span></span><span class="line"><span class="ln">37</span><span class="cl">  加速比: 2.42x
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">find_all
</span></span><span class="line"><span class="ln">40</span><span class="cl">  C++:      0.0312 ms (stdev: 0.0045)
</span></span><span class="line"><span class="ln">41</span><span class="cl">  Python:   0.0823 ms (stdev: 0.0098)
</span></span><span class="line"><span class="ln">42</span><span class="cl">  加速比: 2.64x
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">======================================================================</span></span></code></pre></div><h3 id="效能分析">效能分析</h3>
<table>
  <thead>
      <tr>
          <th>操作類型</th>
          <th>C++ 優勢</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>字元頻率統計</strong></td>
          <td>4-6x</td>
          <td>C++ unordered_map 比 Python dict 更快</td>
      </tr>
      <tr>
          <td><strong>搜尋操作</strong></td>
          <td>2-3x</td>
          <td>C++ string::find 效率高</td>
      </tr>
      <tr>
          <td><strong>大小寫轉換</strong></td>
          <td>0.7x</td>
          <td>Python 內建函式已高度優化</td>
      </tr>
      <tr>
          <td><strong>單字計數</strong></td>
          <td>0.8-1x</td>
          <td>Python split() 非常高效</td>
      </tr>
  </tbody>
</table>
<p><strong>重點觀察</strong>：</p>
<ol>
<li><strong>不是所有操作都能加速</strong>：Python 的內建字串方法（如 <code>upper()</code>、<code>split()</code>）已經用 C 實作，pybind11 包裝反而增加呼叫開銷</li>
<li><strong>複雜操作效益明顯</strong>：需要多次迴圈或資料結構操作的方法（如字元頻率統計）獲益最大</li>
<li><strong>資料量影響顯著</strong>：資料量越大，C++ 的優勢越明顯</li>
</ol>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>純 Python</th>
          <th>pybind11 C++ 綁定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>開發速度</strong></td>
          <td>快</td>
          <td>中（需要 C++ 開發經驗）</td>
      </tr>
      <tr>
          <td><strong>效能</strong></td>
          <td>基準</td>
          <td>特定操作 2-6x 加速</td>
      </tr>
      <tr>
          <td><strong>記憶體使用</strong></td>
          <td>較高</td>
          <td>較低（C++ 記憶體管理）</td>
      </tr>
      <tr>
          <td><strong>除錯難度</strong></td>
          <td>低</td>
          <td>中高（需要 C++ 除錯工具）</td>
      </tr>
      <tr>
          <td><strong>部署複雜度</strong></td>
          <td>簡單</td>
          <td>需要編譯環境</td>
      </tr>
      <tr>
          <td><strong>可維護性</strong></td>
          <td>高</td>
          <td>中（需要維護兩種語言）</td>
      </tr>
  </tbody>
</table>
<h3 id="何時使用-pybind11-綁定-c-類別">何時使用 pybind11 綁定 C++ 類別？</h3>
<p><strong>適合使用</strong>：</p>
<ul>
<li>已有成熟的 C++ 程式庫需要在 Python 中使用</li>
<li>需要精細的記憶體管理</li>
<li>效能瓶頸在資料結構操作而非 I/O</li>
<li>需要與其他 C++ 系統整合</li>
</ul>
<p><strong>不建議使用</strong>：</p>
<ul>
<li>純字串處理（Python 內建已很快）</li>
<li>簡單的資料容器（用 Python dataclass 更簡潔）</li>
<li>快速原型開發</li>
<li>團隊沒有 C++ 經驗</li>
</ul>
<h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>擴展 StringProcessor，新增以下方法：</p>
<ol>
<li><code>join(separator: str, strings: list[str])</code> - 用分隔符串接字串列表</li>
<li><code>pad_left(width: int, char: str)</code> - 左側填充字元</li>
<li><code>pad_right(width: int, char: str)</code> - 右側填充字元</li>
</ol>
<h3 id="進階練習">進階練習</h3>
<p>建立一個 <code>DataBuffer</code> 類別，展示：</p>
<ol>
<li>使用 <code>std::vector&lt;uint8_t&gt;</code> 儲存二進位資料</li>
<li>支援 Python buffer protocol（可與 NumPy 互通）</li>
<li>實作切片操作（<code>__getitem__</code> 支援 slice）</li>
</ol>
<h3 id="挑戰題">挑戰題</h3>
<p>比較三種綁定方式的效能：</p>
<ol>
<li>pybind11 直接綁定</li>
<li>pybind11 + 釋放 GIL</li>
<li>使用 NumPy 陣列避免資料複製</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://pybind11.readthedocs.io/en/stable/classes.html">pybind11 官方文件：類別</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/operators.html">pybind11 官方文件：運算子重載</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html">pybind11 官方文件：智慧指標</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies">pybind11 記憶體管理最佳實踐</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></em></p>
]]></content:encoded></item></channel></rss>