<?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>Python 基础 on On My Way</title>
    <link>https://tuanzi-wow.cn/python/</link>
    <description>Recent content in Python 基础 on On My Way</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <atom:link href="https://tuanzi-wow.cn/python/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>DAY1 · Python 交互模式随手记</title>
      <link>https://tuanzi-wow.cn/python/python-day1/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-day1/</guid>
      <description>Python 解释器交互模式下的第一天随手记：命令行参数、常用内建用法与踩到的语法坑。</description>
      <content:encoded><![CDATA[<h2 id="what-is-shown-here-is-what-idk-before">What is shown here is what idk before!</h2>
<h3 id="此处的应用场景是python解释器的交互模式之下">此处的应用场景是python解释器的交互模式之下:</h3>
<p>Do not laugh at me ! I&rsquo;m REALLY a newbie!!!!</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="n">command</span> <span class="n">arg</span>
</span></span><span class="line"><span class="cl"><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">module</span> <span class="n">arg</span>
</span></span><span class="line"><span class="cl"><span class="o">//</span><span class="n">创建新New</span><span class="err">—</span><span class="n">Item</span> <span class="n">name</span><span class="err">（</span><span class="n">真实的名称</span><span class="err">）</span> <span class="n">ItemType</span> <span class="nb">type</span><span class="err">（</span><span class="n">具体的类型</span><span class="err">）</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>忘掉了的</p>
<h4 id="数字">数字</h4>
<p>除法运算 (<code>/</code>) 总是返回浮点数。<strong>如果要做 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-floor-division">floor division</a> 得到一个整数结果你可以使用 <code>//</code> 运算符；</strong></p>
<p>Something New：
Python 用 <code>**</code> 运算符计算乘方 [<a href="https://docs.python.org/zh-cn/3/tutorial/introduction.html#id3">1]</a>：
交互模式下，上次输出的表达式会赋给变量 <code>_</code>。把 Python 当作计算器时，用该变量实现下一步计算更简单，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">tax = 12.5 / 100
</span></span><span class="line"><span class="cl">price = 100.50
</span></span><span class="line"><span class="cl">price * tax
</span></span><span class="line"><span class="cl">12.5625
</span></span><span class="line"><span class="cl">price + _
</span></span><span class="line"><span class="cl">113.0625
</span></span><span class="line"><span class="cl">round(_, 2)
</span></span><span class="line"><span class="cl">113.06
</span></span></code></pre></td></tr></table>
</div>
</div><p>除了 <a href="https://docs.python.org/zh-cn/3/library/functions.html#int"><code>int</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/functions.html#float"><code>float</code></a>，Python 还支持其他数字类型，例如 <a href="https://docs.python.org/zh-cn/3/library/decimal.html#decimal.Decimal"><code>Decimal</code></a> 或 <a href="https://docs.python.org/zh-cn/3/library/fractions.html#fractions.Fraction"><code>Fraction</code></a>。 Python 还内置支持 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#typesnumeric">复数</a>，后缀 <code>j</code> 或 <code>J</code> 用于表示虚数 (例如 <code>3+5j</code>)。(wow 复数，之前没有了解过这个表达形式)</p>
<h4 id="文本有str类型表示">文本：有str类型表示</h4>
<p>‘’ 和 ‘’  “无差别
要标示引号本身，我们需要对它进行“转义”，<strong>即在前面加一个 <code>\</code></strong>。或者，我们也可以使用不同类型的引号:
如果要在str使用‘ ，我们可以整体上使用“  ”反之亦然；不过统一的\貌似是一个更好的选择如果不希望前置 <code>\</code> 的字符转义成特殊字符，可以使用 <em>原始字符串</em>，在引号前添加 <code>r</code> 即可：</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;C:</span><span class="se">\t</span><span class="s1">his</span><span class="se">\n</span><span class="s1">ame&#39;</span><span class="p">)</span>  <span class="c1"># 这里 \t 表示制表符，\n 表示换行符</span>
</span></span><span class="line"><span class="cl"><span class="n">C</span><span class="p">:</span>      <span class="n">his</span>
</span></span><span class="line"><span class="cl"><span class="n">ame</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;C:\this\name&#39;</span><span class="p">)</span>  <span class="c1"># 请注意引号前的 r</span>
</span></span><span class="line"><span class="cl"><span class="n">C</span><span class="p">:</span>\<span class="n">this</span>\<span class="n">name</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>原始字符串还有一个微妙的限制：一个原始字符串不能以奇数个 <code>\</code> 字符结束；请参阅 <a href="https://docs.python.org/zh-cn/3/faq/programming.html#faq-programming-raw-string-backslash">此 FAQ 条目</a> 了解更多信息及绕过的办法。字符串字面值可以跨越多行。 一种做法是使用三重引号: <code>&quot;&quot;&quot;...&quot;&quot;&quot;</code> 或 <code>'''...'''</code>。 行结束符会自动包括在字符串中，但可以通过在行尾添加 <code>\</code> 来避免此行为。在下面的例子中，开头的换行符将不会被包括:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;</span><span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="s2">Usage: thingy [OPTIONS]
</span></span></span><span class="line"><span class="cl"><span class="s2">     -h                        Display this usage message
</span></span></span><span class="line"><span class="cl"><span class="s2">     -H hostname               Hostname to connect to
</span></span></span><span class="line"><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">Usage</span><span class="p">:</span> <span class="n">thingy</span> <span class="p">[</span><span class="n">OPTIONS</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">     <span class="o">-</span><span class="n">h</span>                        <span class="n">Display</span> <span class="n">this</span> <span class="n">usage</span> <span class="n">message</span>
</span></span><span class="line"><span class="cl">     <span class="o">-</span><span class="n">H</span> <span class="n">hostname</span>               <span class="n">Hostname</span> <span class="n">to</span> <span class="n">connect</span> <span class="n">to</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>字符串字面值的自动拼接</p>
<p>相邻的两个或多个 <em>字符串字面值</em> （引号标注的字符）会自动合并：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&#39;Py&#39; &#39;thon&#39;
</span></span><span class="line"><span class="cl">&#39;Python&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>拼接分隔开的长字符串时，这个功能特别实用：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">text = (&#39;Put several strings within parentheses &#39;
</span></span><span class="line"><span class="cl">        &#39;to have them joined together.&#39;)
</span></span><span class="line"><span class="cl">text
</span></span><span class="line"><span class="cl">&#39;Put several strings within parentheses to have them joined together.&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>这项功能只能用于两个字面值，不能用于变量或表达式，合并变量&amp;表达式要使用+：</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">prefix = &#39;Py&#39;
</span></span><span class="line"><span class="cl">prefix &#39;thon&#39;  # 不能拼接变量和字符串字面值
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 1
</span></span><span class="line"><span class="cl">    prefix &#39;thon&#39;
</span></span><span class="line"><span class="cl">           ^^^^^^
</span></span><span class="line"><span class="cl">SyntaxError: invalid syntax
</span></span><span class="line"><span class="cl">(&#39;un&#39; * 3) &#39;ium&#39;
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 1
</span></span><span class="line"><span class="cl">    (&#39;un&#39; * 3) &#39;ium&#39;
</span></span><span class="line"><span class="cl">               ^^^^^
</span></span><span class="line"><span class="cl">SyntaxError: invalid syntax
</span></span></code></pre></td></tr></table>
</div>
</div><p>字符串的索引居然能够支持负数，从右边开始计数字符串支持 <em>索引</em> （下标访问），第一个字符的索引是 0。单字符没有专用的类型，就是长度为一的字符串：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">word = &#39;Python&#39;
</span></span><span class="line"><span class="cl">word[0]  # 0 号位的字符
</span></span><span class="line"><span class="cl">&#39;P&#39;
</span></span><span class="line"><span class="cl">word[5]  # 5 号位的字符
</span></span><span class="line"><span class="cl">&#39;n&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>索引还支持负数，用负数索引时，从右边开始计数：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">word[-1]  # 最后一个字符
</span></span><span class="line"><span class="cl">&#39;n&#39;
</span></span><span class="line"><span class="cl">word[-2]  # 倒数第二个字符
</span></span><span class="line"><span class="cl">&#39;o&#39;
</span></span><span class="line"><span class="cl">word[-6]
</span></span><span class="line"><span class="cl">&#39;P&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>字符串的切：用于获取子字符串（substr来了说是）</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">word[0:2]  # 从 0 号位 (含) 到 2 号位 (不含) 的字符
</span></span><span class="line"><span class="cl">&#39;Py&#39;
</span></span><span class="line"><span class="cl">word[2:5]  # 从 2 号位 (含) 到 5 号位 (不含) 的字符
</span></span><span class="line"><span class="cl">&#39;tho&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>切片索引的默认值：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">word[:2]   # 从开头到 2 号位 (不含) 的字符
</span></span><span class="line"><span class="cl">&#39;Py&#39;
</span></span><span class="line"><span class="cl">word[4:]   # 从 4 号位 (含) 到末尾
</span></span><span class="line"><span class="cl">&#39;on&#39;
</span></span><span class="line"><span class="cl">word[-2:]  # 从倒数第二个 (含) 到末尾
</span></span><span class="line"><span class="cl">&#39;on&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>注意，<strong>输出结果包含切片开始，但不包含切片结束</strong>。因此，<code>s[:i] + s[i:]</code> 总是等于 <code>s</code>：
都是如果结束索引是默认值，那么实际上还有一个终结符，我们可以理解为不包含这个终结符但是包含最后一位
可以换一个方式理解：切片是索引之间
直接通过索引访问单个位置可能会出现索引越界，但是切片会自动处理索引越界
Python的字符串不可修改，是immutable的（怎么和JAVA一样啊，恼！！！）
字符串长度获取：内置函数：len();
我CHOVY，ntm讲字符串给我讲好了啊！！！
下面是字符串的一些方法！！！
自己去这里找
<a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#textseq">https://docs.python.org/zh-cn/3/library/stdtypes.html#textseq</a></p>
<h4 id="列表mutable">列表：mutable</h4>
<p>支持索引，切片，合并
append（）；len（）：为切片赋值可以改变列表大小，甚至清空整个列表：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">letters = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;, &#39;g&#39;]
</span></span><span class="line"><span class="cl">letters
</span></span><span class="line"><span class="cl">[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;, &#39;g&#39;]
</span></span><span class="line"><span class="cl"># 替换一些值
</span></span><span class="line"><span class="cl">letters[2:5] = [&#39;C&#39;, &#39;D&#39;, &#39;E&#39;]
</span></span><span class="line"><span class="cl">letters
</span></span><span class="line"><span class="cl">[&#39;a&#39;, &#39;b&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;f&#39;, &#39;g&#39;]
</span></span><span class="line"><span class="cl"># 现在移除它们
</span></span><span class="line"><span class="cl">letters[2:5] = []
</span></span><span class="line"><span class="cl">letters
</span></span><span class="line"><span class="cl">[&#39;a&#39;, &#39;b&#39;, &#39;f&#39;, &#39;g&#39;]
</span></span><span class="line"><span class="cl"># 通过用一个空列表替代所有元素来清空列表
</span></span><span class="line"><span class="cl">letters[:] = []
</span></span><span class="line"><span class="cl">letters
</span></span><span class="line"><span class="cl">[]
</span></span></code></pre></td></tr></table>
</div>
</div><p>嵌套列表（注意不是合并哦哦哦哦哦！！！！！！）</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a = [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]
</span></span><span class="line"><span class="cl">n = [1, 2, 3]
</span></span><span class="line"><span class="cl">x = [a, n]
</span></span><span class="line"><span class="cl">x
</span></span><span class="line"><span class="cl">[[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;], [1, 2, 3]]
</span></span><span class="line"><span class="cl">x[0]
</span></span><span class="line"><span class="cl">[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;]
</span></span><span class="line"><span class="cl">x[0][1]
</span></span><span class="line"><span class="cl">&#39;b&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>
<p>关键字参数 <em>end</em> 可以取消输出后面的换行, 或用另一个字符串结尾：</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a, b = 0, 1
</span></span><span class="line"><span class="cl">while a &lt; 1000:
</span></span><span class="line"><span class="cl">    print(a, end=&#39;,&#39;)
</span></span><span class="line"><span class="cl">    a, b = b, a+b
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<p><code>**</code> 比 <code>-</code> 的优先级更高, 所以 <code>-3**2</code> 会被解释成 <code>-(3**2)</code> ，因此，结果是 <code>-9</code>。要避免这个问题，并且得到 <code>9</code>, 可以用 <code>(-3)**2</code>。</p>
<p>[<a href="https://docs.python.org/zh-cn/3/tutorial/introduction.html#id2">2</a>]</p>
<p>与其他语言不同，特殊字符如 <code>\n</code> 在单引号 (<code>'...'</code>) 和双引号 (<code>&quot;...&quot;</code>) 里的意义一样。 这两种引号唯一的区别是，不需要在单引号里转义双引号 <code>&quot;</code> (但此时必须把单引号转义成 <code>\'</code>)，反之亦然。</p>
<h4 id="更多的控制流工具">更多的控制流工具</h4>
<h5 id="range函数">range（）函数：</h5>
<p>内置函数 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#range"><code>range()</code></a> 用于生成等差数列：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">for i in range(5):
</span></span><span class="line"><span class="cl">    print(i)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">0
</span></span><span class="line"><span class="cl">1
</span></span><span class="line"><span class="cl">2
</span></span><span class="line"><span class="cl">3
</span></span><span class="line"><span class="cl">4
</span></span></code></pre></td></tr></table>
</div>
</div><p>生成的序列绝不会包括给定的终止值；<code>range(10)</code> 生成 10 个值——长度为 10 的序列的所有合法索引。range 可以不从 0 开始，且可以按给定的步长递增（即使是负数步长）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">list(range(5, 10))
</span></span><span class="line"><span class="cl">[5, 6, 7, 8, 9]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">list(range(0, 10, 3))
</span></span><span class="line"><span class="cl">[0, 3, 6, 9]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">list(range(-10, -100, -30))
</span></span><span class="line"><span class="cl">[-10, -40, -70]
</span></span></code></pre></td></tr></table>
</div>
</div><p>要按索引迭代序列，可以组合使用 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#range"><code>range()</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/functions.html#len"><code>len()</code></a>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">a = [&#39;Mary&#39;, &#39;had&#39;, &#39;a&#39;, &#39;little&#39;, &#39;lamb&#39;]
</span></span><span class="line"><span class="cl">for i in range(len(a)):
</span></span><span class="line"><span class="cl">    print(i, a[i])
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">0 Mary
</span></span><span class="line"><span class="cl">1 had
</span></span><span class="line"><span class="cl">2 a
</span></span><span class="line"><span class="cl">3 little
</span></span><span class="line"><span class="cl">4 lamb
</span></span></code></pre></td></tr></table>
</div>
</div><p>不过大多数情况下 <a href="https://docs.python.org/zh-cn/3/library/functions.html#enumerate"><code>enumerate()</code></a> 函数很方便，详见 <a href="https://docs.python.org/zh-cn/3/tutorial/datastructures.html#tut-loopidioms">循环的技巧</a>。</p>
<p>如果直接打印一个 range 会发生意想不到的事情：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">range(10)
</span></span><span class="line"><span class="cl">range(0, 10)
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#range"><code>range()</code></a> 返回的对象在很多方面和列表的行为一样，但其实它和列表不一样。该对象只有在被迭代时才一个一个地返回所期望的列表项，并没有真正生成过一个含有全部项的列表，从而节省了空间。</p>
<p>这种对象称为可迭代对象 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-iterable">iterable</a>，适合作为需要获取一系列值的函数或程序构件的参数。<a href="https://docs.python.org/zh-cn/3/reference/compound_stmts.html#for"><code>for</code></a> 语句就是这样的程序构件；以可迭代对象作为参数的函数例如 <a href="https://docs.python.org/zh-cn/3/library/functions.html#sum"><code>sum()</code></a>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sum(range(4))  # 0 + 1 + 2 + 3
</span></span><span class="line"><span class="cl">6
</span></span></code></pre></td></tr></table>
</div>
</div><p>后续我们会看到更多返回可迭代对象并以可迭代对象作为参数的函数。 在 <a href="https://docs.python.org/zh-cn/3/tutorial/datastructures.html#tut-structures">数据结构</a> 一章中，我们将讨论 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#list"><code>list()</code></a> 的更多细节。</p>
<p>列表的常见方法见
<a href="https://docs.python.org/zh-cn/3/tutorial/datastructures.html">https://docs.python.org/zh-cn/3/tutorial/datastructures.html</a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">append（value）:
</span></span><span class="line"><span class="cl">extend(iterable):
</span></span><span class="line"><span class="cl">insert(index,value):
</span></span><span class="line"><span class="cl">remove(value):
</span></span><span class="line"><span class="cl">pop(index=-1):
</span></span><span class="line"><span class="cl">clear():
</span></span><span class="line"><span class="cl">index(value,start,stop)
</span></span><span class="line"><span class="cl">count(value);
</span></span><span class="line"><span class="cl">sort(*,key=noe,reveres = False);
</span></span><span class="line"><span class="cl">reveres():
</span></span><span class="line"><span class="cl">copy:
</span></span></code></pre></td></tr></table>
</div>
</div><h5 id="列表实现堆栈后进先出">列表实现堆栈：后进先出</h5>
<p>append();pop()</p>
<h5 id="列表实现队列性能很差最好使用collectionddeque">列表实现队列：性能很差，最好使用collectiond.deque</h5>
<h5 id="列表推导式">列表推导式:</h5>
<p>创建列表非常方便
筛选满足某些特定条件的元素/对全部元素进行操作</p>
<h5 id="嵌套的列表推导式">嵌套的列表推导式</h5>
<p>实际应用最好用内置函数替代复杂的流程函数</p>
<h5 id="del区分与pop">del：区分与pop</h5>
<p>可接单个元素如a[0],切片，或者单个变量a</p>
<h5 id="元组和序列">元组和序列</h5>
<p>元组：通过&rsquo;,&lsquo;隔开，通常使用（）标注，imutable，但是可以存储mutable的元素如列表
特别的单个元组：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">empty = ()
</span></span><span class="line"><span class="cl">singleton = &#39;hello&#39;,    # &lt;-- 注意末尾的逗号
</span></span><span class="line"><span class="cl">len(empty)
</span></span><span class="line"><span class="cl">0
</span></span><span class="line"><span class="cl">len(singleton)
</span></span><span class="line"><span class="cl">1
</span></span><span class="line"><span class="cl">singleton
</span></span><span class="line"><span class="cl">(&#39;hello&#39;,)
</span></span></code></pre></td></tr></table>
</div>
</div><p>解包：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">x, y, z = t
</span></span></code></pre></td></tr></table>
</div>
</div><h5 id="集合set-无序去重">集合：set 无序，去重</h5>
<p>创建空集合只能用set（）；创建可以用{}和set（）；
集合推导式</p>
<h5 id="字典">字典：</h5>
<p>以key（键）为索引；任何不可变类型都可以作为key
特别的，元组仅包含（字符串，元组，数字）时也可以为key，但是如果它直接或者间接包含可变元素，则不可
键对值的集合，键唯一</p>
<p>下标操作d[key]可能（空值时即key不存在）会导致KeyError，最好用get（），返回值或者none：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">list（d） ：获得所有key的列表，不包含value
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">sort（），in
</span></span><span class="line"><span class="cl">dict（）：构造函数
</span></span></code></pre></td></tr></table>
</div>
</div><p>字典推导式：关键字是比较简单的字符串时，直接用关键字参数指定键值对更便捷：</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dict(sape=4139, guido=4127, jack=4098)
</span></span><span class="line"><span class="cl">{&#39;sape&#39;: 4139, &#39;guido&#39;: 4127, &#39;jack&#39;: 4098}
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="循环的技巧">循环的技巧</h4>
<p>同时获得字典的（key，value） ：item（）；
同时获得（index，value）：enumerate（）；
同时循环两个或者多个序列时：zip（）；
配置这个看的更明确</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">questions = [&#39;name&#39;, &#39;quest&#39;, &#39;favorite color&#39;]
</span></span><span class="line"><span class="cl">answers = [&#39;lancelot&#39;, &#39;the holy grail&#39;, &#39;blue&#39;]
</span></span><span class="line"><span class="cl">for q, a in zip(questions, answers):
</span></span><span class="line"><span class="cl">    print(&#39;What is your {0}?  It is {1}.&#39;.format(q, a))
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">What is your name?  It is lancelot.
</span></span><span class="line"><span class="cl">What is your quest?  It is the holy grail.
</span></span><span class="line"><span class="cl">What is your favorite color?  It is blue.
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">逆向：reverse（）
</span></span><span class="line"><span class="cl">排序：sorted（）
</span></span><span class="line"><span class="cl">去重：set（）
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="条件控制">条件控制</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">in  ；not in
</span></span><span class="line"><span class="cl">is ；not is
</span></span><span class="line"><span class="cl">链式比较操作：a &lt; b == c
</span></span><span class="line"><span class="cl">优先级:not &gt; and &gt; or
</span></span></code></pre></td></tr></table>
</div>
</div><h3></h3>
]]></content:encoded>
    </item>
    <item>
      <title>6. 模块</title>
      <link>https://tuanzi-wow.cn/python/python-06-modules/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-06-modules/</guid>
      <description>模块的定义与导入、标准模块、dir() 与包的层级结构。</description>
      <content:encoded><![CDATA[<h2 id="定义">定义：</h2>
<p>模块是包含 Python 定义和语句的文件。其文件名是模块名加后缀名 <code>.py</code> 。在模块内部，通过全局变量 <code>__name__</code> 可以获取模块名（即字符串）。</p>
<h3 id="导入模块">导入模块：</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import name(模块的真实名字)
</span></span></code></pre></td></tr></table>
</div>
</div><p>本质将模块名称添加到namespeac而非把定义的函数添加进去</p>
<h2 id="61-模块详解">6.1 模块详解：</h2>
<p>模块包含可执行语句及函数定义。这些语句用于初始化模块，且仅在 import 语句 <em>第一次</em> 遇到模块名时执行。
每个模块都有它自己的私有符号表，该表被定义在该模块里的所有函数当作全局符号表使用。
您可以使用与引用模块函数相同的语法去访问一个模块的全局变量，即 <code>modname.itemname</code></p>
<h4 id="导入其他模块import">导入其他模块：import</h4>
<p>被放置于一个模块的最高层级，则被导入的模块名称会被添加到该模块的全局命名空间。
import的变式1：将来自某个模块的名称直接导入到导入方的命名空间里面</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from fibo import fib, fib2
</span></span><span class="line"><span class="cl">fib(500)
</span></span><span class="line"><span class="cl">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
</span></span></code></pre></td></tr></table>
</div>
</div><p>变式2：导入模块内定义的所有名称（不包含以_开头的名称）</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from fibo import *
</span></span><span class="line"><span class="cl">fib(500)
</span></span><span class="line"><span class="cl">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
</span></span></code></pre></td></tr></table>
</div>
</div><p>不建议：可能会覆盖已经定义的名称</p>
<p>变式3：模块名后接as</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import fibo from fib
</span></span><span class="line"><span class="cl">fib.fib(500)
</span></span></code></pre></td></tr></table>
</div>
</div><p>或者变式1，3结合</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from fibo import fib as fibonacci
</span></span><span class="line"><span class="cl">fibonacci(500)
</span></span><span class="line"><span class="cl">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="备注">备注</h4>
<p>每次解释器会话只导入一次模块，若模块内容更改，需要重启解释器
如仅交互测试一个模块，可以使用<a href="https://docs.python.org/zh-cn/3/library/importlib.html#importlib.reload"><code>importlib.reload()</code></a>，例如 <code>import importlib; importlib.reload(modulename)</code>。</p>
<h3 id="611以脚本方式执行模块">6.1.1.以脚本方式执行模块</h3>
<p>最常见命令：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">python fibo.py &lt;arguments&gt;（这个参数的必须的）
</span></span></code></pre></td></tr></table>
</div>
</div><p>导入模块的代码，但是会将_name_命名为&quot;<strong>main</strong>&quot;(这里前面和后面都有一个__，但是因为md原因导致没有了)</p>
<p>例如</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">python fibo.py 50
</span></span><span class="line"><span class="cl">0 1 1 2 3 5 8 13 21 34
</span></span></code></pre></td></tr></table>
</div>
</div><p>相当于</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">if __name__ == &#34;__main__&#34;:
</span></span><span class="line"><span class="cl">    import sys
</span></span><span class="line"><span class="cl">    fib(int(sys.argv[1]))
</span></span></code></pre></td></tr></table>
</div>
</div><p>该文件既可作为模块又可以作为脚本
而像下面这种导入其他模块则不会</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import fibo 
</span></span></code></pre></td></tr></table>
</div>
</div><p>用于为模块提供一个便捷的用户接口，或用于测试</p>
<h3 id="612模块的搜索路径">6.1.2.模块的搜索路径</h3>
<p>当导入一个名为 <code>spam</code> 的模块时，解释器首先会搜索具有该名称的内置模块。 这些模块的名称在 <a href="https://docs.python.org/zh-cn/3/library/sys.html#sys.builtin_module_names"><code>sys.builtin_module_names</code></a> 中列出。 如果未找到，它将在变量 <a href="https://docs.python.org/zh-cn/3/library/sys.html#sys.path"><code>sys.path</code></a> 所给出的目录列表中搜索名为 <code>spam.py</code> 的文件。 <code>sys.path</code> 是从这些位置初始化的:</p>
<ul>
<li>被命令行直接运行的脚本所在的目录（或未指定文件时的当前目录）。</li>
<li><a href="https://docs.python.org/zh-cn/3/using/cmdline.html#envvar-PYTHONPATH"><code>PYTHONPATH</code></a> （目录列表，与 shell 变量 <code>PATH</code> 的语法一样）。</li>
<li>依赖于安装的默认值（按照惯例包括一个 <code>site-packages</code> 目录，由 <a href="https://docs.python.org/zh-cn/3/library/site.html#module-site"><code>site</code></a> 模块处理）。</li>
</ul>
<p>更多细节请参阅 <a href="https://docs.python.org/zh-cn/3/library/sys_path_init.html#sys-path-init">sys.path 模块搜索路径的初始化</a>。</p>
<h4 id="备注-1">备注</h4>
<p>在支持符号链接的文件系统中，“被命令行直接运行的脚本所在的目录”是符号链接最终指向的目录。换句话说，符号链接所在的目录并 <strong>没有</strong> 被添加至模块搜索路径。</p>
<p>初始化后，Python 程序可以更改 <a href="https://docs.python.org/zh-cn/3/library/sys.html#sys.path"><code>sys.path</code></a>。脚本所在的目录先于标准库所在的路径被搜索。这意味着，脚本所在的目录如果有和标准库同名的文件，那么加载的是该目录里的，而不是标准库的。这一般是一个错误，除非这样的替换是你有意为之。详见 <a href="https://docs.python.org/zh-cn/3/tutorial/modules.html#tut-standardmodules">标准模块</a>。</p>
<h3 id="613已编译的python文件">6.1.3.”已编译的“Python文件</h3>
<p>模块的编译版本存放在&ndash;pycache__目录中，文件名为module.version.pyc,</p>
<p>version:对编译文件格式进行编码，一般是版本号
可以让不同版本的Python编译的模块可以共存
例子：CPython 的 3.3 发行版中，spam.py 的编译版本缓存为 <code>__pycache__/spam.cpython-33.pyc</code></p>
<p>Python会自动检查编译版本和源码的修改日期来查看编译版是否过期，是否需要重新编译
编译模块与平台无关
Python不检查缓存的两种情况
1.从命令行直接载入的模块：每次重新编译且不存储结果
2.没有源模块
隐藏源代码：将所有源代码编程编译之后的版本，并储存在源目录而非缓存目录中）</p>
<p>ps：
.pyc的读取未必比.py快，只是加载速度更快
<a href="https://docs.python.org/zh-cn/3/library/compileall.html#module-compileall"><code>compileall</code></a> 模块可以为一个目录下的所有模块创建 .pyc 文件。</p>
<h2 id="62标准模块">6.2.标准模块</h2>
<p>Python自带的，在Python的库参考中另外描述
这些模块集是一个配置选项，并且还依赖于底层的操作系统
例如winreg只在WIndows系统上提供
但是sys模块内嵌到每一个Python解释器，sys.psq和sys.ps2变量定义了一些字符，可以作为主提示符和辅助提示符
变量的sys.path：字符串列表，用于确定解释器的模块搜索路径
从环境变量PYTHONPATH提取默认路径进行初始化，若未设置PYTHONPATH，则使用内置的默认路径
可以通过标准列表操作修改该变量</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import sys
</span></span><span class="line"><span class="cl">sys.path.append(&#39;/ufs/guido/lib/python&#39;)
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="63dir函数">6.3.dir()函数</h2>
<p>查找模块定义的名称，返回值：经过排序的字符串列表
没有参数时：
返回值：当前已经定义的名称
包括：变量，模块，函数&hellip;&hellip;
但是不会列出内置函数和变量的名称
这些内容的定义在标准模块 <a href="https://docs.python.org/zh-cn/3/library/builtins.html#module-builtins"><code>builtins</code></a> 中：</p>
<h2 id="64-包">6.4. 包</h2>
<p>通过”带点号模块名“来狗仔Python模块命名空间的一种方式
可以让不同包的作者不用担心彼此的全局变量名，比如模块名冲突</p>
<p>导入包时，Python 搜索 <code>sys.path</code> 里的目录，查找包的子目录。</p>
<p>需要有 <code>__init__.py</code> 文件才能让 Python 将包含该文件的目录当作包来处理（除非使用 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-namespace-package">namespace package</a>，这是一个相对高级的特性）。 这可以防止重名的目录如 <code>string</code> 在无意中屏蔽后继出现在模块搜索路径中的有效模块。 在最简单的情况下，<code>__init__.py</code> 可以只是一个空文件，但它也可以执行包的初始化代码或设置 <code>__all__</code> 变量，这将在稍后详细描述。</p>
<p>还可以从包中导入单个模块，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import sound.effects.echo
</span></span></code></pre></td></tr></table>
</div>
</div><p>这将加载子模块 <code>sound.effects.echo</code>。 它必须通过其全名来引用。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
</span></span></code></pre></td></tr></table>
</div>
</div><p>另一种导入子模块的方法是 ：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from sound.effects import echo
</span></span></code></pre></td></tr></table>
</div>
</div><p>这也会加载子模块 <code>echo</code>，并使其不必加包前缀，因此可按如下方式使用:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echo.echofilter(input, output, delay=0.7, atten=4)
</span></span></code></pre></td></tr></table>
</div>
</div><p>Import 语句的另一种变体是直接导入所需的函数或变量：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from sound.effects.echo import echofilter
</span></span></code></pre></td></tr></table>
</div>
</div><p>同样，这将加载子模块 <code>echo</code>，但这使其函数 <code>echofilter()</code> 直接可用:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">echofilter(input, output, delay=0.7, atten=4)
</span></span></code></pre></td></tr></table>
</div>
</div><p>注意，使用 <code>from package import item</code> 时，item 可以是包的子模块（或子包），也可以是包中定义的函数、类或变量等其他名称。<code>import</code> 语句首先测试包中是否定义了 item；如果未在包中定义，则假定 item 是模块，并尝试加载。如果找不到 item，则触发 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#ImportError"><code>ImportError</code></a> 异常。</p>
<p>相反，使用 <code>import item.subitem.subsubitem</code> 句法时，除最后一项外，每个 item 都必须是包；最后一项可以是模块或包，但不能是上一项中定义的类、函数或变量。</p>
<h3 id="641-从包中导入">6.4.1. 从包中导入*</h3>
<p>提供包的显式索引</p>
<p>导入在init.py 代码定义了列表 all
发布新版本时，应更新该列表
例如：<code>sound/effects/__init__.py</code> 文件可以包含以下代码：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">__all__ = [&#34;echo&#34;, &#34;surround&#34;, &#34;reverse&#34;]
</span></span></code></pre></td></tr></table>
</div>
</div><p>这意味着 <code>from sound.effects import *</code> 将导入 <code>sound.effects</code> 包的三个命名子模块。请注意子模块可能会受到本地定义名称的影响。 例如，如果你在 <code>sound/effects/__init__.py</code> 文件中添加了一个 <code>reverse</code> 函数，<code>from sound.effects import *</code> 将只导入 <code>echo</code> 和 <code>surround</code> 这两个子模块，但 <strong>不会</strong> 导入 <code>reverse</code> 子模块，因为它被本地定义的 <code>reverse</code> 函数所遮挡:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">__all__ = [
</span></span><span class="line"><span class="cl">    &#34;echo&#34;,      # 指向 &#39;echo.py&#39; 文件
</span></span><span class="line"><span class="cl">    &#34;surround&#34;,  # 指向 &#39;surround.py&#39; 文件
</span></span><span class="line"><span class="cl">    &#34;reverse&#34;,   # !!! 现在指向 &#39;reverse&#39; 函数 !!!
</span></span><span class="line"><span class="cl">]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">def reverse(msg: str):  # &lt;-- 此名称将覆盖 &#39;reverse.py&#39; 子模块
</span></span><span class="line"><span class="cl">    return msg[::-1]    #     针对 &#39;from sound.effects import *&#39; 的情况
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="没有定义____all____">没有定义____all____:</h4>
<p>有点没懂</p>
<h3 id="642-相对导入">6.4.2. 相对导入</h3>
<p>使用前导符号.来完成
一般用于子模块</p>
]]></content:encoded>
    </item>
    <item>
      <title>7. 输入和输出</title>
      <link>https://tuanzi-wow.cn/python/python-07-io/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-07-io/</guid>
      <description>更复杂的输出格式（f-string、str.format）与文件的读写方式。</description>
      <content:encoded><![CDATA[<h2 id="71更加复杂的输出格式">7.1.更加复杂的输出格式</h2>
<h3 id="格式化字符串字面值">格式化字符串字面值</h3>
<p>在字符串开头的引号/三引号之前加f/F
特性：可以通过{}在字符之间输入引用的变量，或者字面值的Python表达式
例子如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">year = 2016
</span></span><span class="line"><span class="cl">event = &#39;Referendum&#39;
</span></span><span class="line"><span class="cl">f&#39;Results of the {year} {event}&#39;
</span></span><span class="line"><span class="cl">&#39;Results of the 2016 Referendum&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><h4 id="strformat">str.format（）:</h4>
<p>特性：1.同上，但你需要提供详细的格式化指令和待格式化的信息
例子：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">yes_votes = 42_572_654
</span></span><span class="line"><span class="cl">total_votes = 85_705_149
</span></span><span class="line"><span class="cl">percentage = yes_votes / total_votes
</span></span><span class="line"><span class="cl">&#39;{:-9} YES votes  {:2.2%}&#39;.format(yes_votes, percentage)
</span></span><span class="line"><span class="cl">&#39; 42572654 YES votes  49.67%&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>解释：
注意此处的输出
-9：&quot;-&ldquo;表示只有在复数是才显示负号，+表示总是显示正负号
例如 {&rsquo;&rsquo;:+&rsquo;&rsquo;}.format(100)  输出+100;
{&rsquo;&rsquo;:+&rsquo;&rsquo;}.format(-100)  输出-100;
{&rsquo;&rsquo;:-&rsquo;&rsquo;}.format(100)  输出100;
{&rsquo;&rsquo;:-&rsquo;&rsquo;}.format(-100)  输出-100;
&lsquo;9&rsquo;表示最小宽度，没有达到则需要填充，比如上面只有八位，在前面填充了一个空格；
{:2.2%} ：
第一个2也表示整数部分最小宽度，因达到两位所以无影响
第二个2表示小数点后保留两位；
百分号表示用%表示</p>
<h4 id="str和repr把值转化成字符串">str()和repr():把值转化成字符串</h4>
<p>不需要花哨输出，用于快速显示变量进行调试</p>
<h4 id="string-模块通过-stringtemplate-提供了一种基于正则表达式的简单模板方法支持"><a href="https://docs.python.org/zh-cn/3/library/string.html#module-string"><code>string</code></a> 模块通过 <a href="https://docs.python.org/zh-cn/3/library/string.html#string.Template"><code>string.Template</code></a> 提供了一种基于正则表达式的简单模板方法支持。</h4>
<p>这种方式为字符串中的值替换提供了另一种途径：使用类似 <code>$x</code> 的占位符，并将其替换为字典中的对应值。该语法使用简便，但在格式控制方面提供的功能较为有限。</p>
<h3 id="711格式化字符串字面值">7.1.1.格式化字符串字面值</h3>
<p>字符串前夹f或F，通过{expression}表达式，把Python变量引入字符串中
格式说明符：可选，便于更好控制格式化值的方式，写在表达式的后面
例1：将pi舍入到小数点后三维  {math.pi:.3f}
例2：再：传递整数，表示最小字符宽度，常于用列对齐
常用于格式化的修饰符及其作用：
<code>'!a'</code> 应用 <a href="https://docs.python.org/zh-cn/3/library/functions.html#ascii"><code>ascii()</code></a> ，<code>'!s'</code> 应用 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#str"><code>str()</code></a>，<code>'!r'</code> 应用 <a href="https://docs.python.org/zh-cn/3/library/functions.html#repr"><code>repr()</code></a>：
=的作用：{expression = }将其拓展为 expression = value</p>
<h3 id="712字符串format方法">7.1.2.字符串format方法</h3>
<p>基本用法：
例1：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s1">&#39;We are the </span><span class="si">{}</span><span class="s1"> who say &#34;</span><span class="si">{}</span><span class="s1">!&#34;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s1">&#39;knights&#39;</span><span class="p">,</span> <span class="s1">&#39;Ni&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"><span class="n">We</span> <span class="n">are</span> <span class="n">the</span> <span class="n">knights</span> <span class="n">who</span> <span class="n">say</span> <span class="s2">&#34;Ni!&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>{}替换为传递给format方法的对象：</strong>
<strong>{}内的数字：表示传递的对象的位置</strong>，例如</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">print(&#39;{0} and {1}&#39;.format(&#39;spam&#39;, &#39;eggs&#39;))
</span></span><span class="line"><span class="cl">spam and eggs
</span></span><span class="line"><span class="cl">print(&#39;{1} and {0}&#39;.format(&#39;spam&#39;, &#39;eggs&#39;))
</span></span><span class="line"><span class="cl">eggs and spam
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>通过关键字参数名引入value</strong></p>
<p>例：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">print(&#39;This {food} is {adjective}.&#39;.format(
</span></span><span class="line"><span class="cl">      food=&#39;spam&#39;, adjective=&#39;absolutely horrible&#39;))
</span></span><span class="line"><span class="cl">This spam is absolutely horrible.
</span></span></code></pre></td></tr></table>
</div>
</div><p>关键词参数和位置参数可以组合使用，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">print(&#39;The story of {0}, {1}, and {other}.&#39;.format(&#39;Bill&#39;, &#39;Manfred&#39;,
</span></span><span class="line"><span class="cl">                                                   other=&#39;Georg&#39;))
</span></span><span class="line"><span class="cl">The story of Bill, Manfred, and Georg.
</span></span></code></pre></td></tr></table>
</div>
</div><p>按名称引入变量进行格式化。可以通过字典传递，使用[]进行访问
例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">table = {&#39;Sjoerd&#39;: 4127, &#39;Jack&#39;: 4098, &#39;Dcab&#39;: 8637678}
</span></span><span class="line"><span class="cl">print(&#39;Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; &#39;
</span></span><span class="line"><span class="cl">      &#39;Dcab: {0[Dcab]:d}&#39;.format(table))
</span></span><span class="line"><span class="cl">Jack: 4098; Sjoerd: 4127; Dcab: 8637678
</span></span></code></pre></td></tr></table>
</div>
</div><p>详解：此处的{0[Jack]:d}中参数的含义 0表示第零个参数，即table这个字典，Jack为关键字参数不必多说，：d表示demical，用十进制表示，绝非double
除此之外，此处的table还可以通过**作为参数，此时就不需要通过[]来访问了
例如</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">print(&#39;Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}&#39;.format(**table))
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="713手动格式化字符串">7.1.3.手动格式化字符串</h3>
<p>蠢蠢的，自己看</p>
<h3 id="714旧式字符串格式化方法">7.1.4.旧式字符串格式化方法</h3>
<p>%用于字符串插值，感觉也蠢蠢的</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import math
</span></span><span class="line"><span class="cl">print(&#39;The value of pi is approximately %5.3f.&#39; % math.pi)
</span></span><span class="line"><span class="cl">The value of pi is approximately 3.142.
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="72读写文件">7.2.读写文件</h2>
<p>open（）的应用：
返回值：一个file object，参数open（filename,mode,encoding = none）
各个参数的意义：
filename：文件名字符串
mode：描述对文件的操作，包含以下几种值：
r：read only，表示只读	w：表示只写	a：表示打开文件并追加内容，将写入的数据写入文件末尾	r+：进行读写	默认值为r
encoding:选择的编码，一般默认UTF-8；在模式后面加b，可以使用binary mode打开文件，二级制数据以bytes对象形式进行读写的，该情况不允许指定encoding
而默认情况是以text mode打开
读取文件，会把平台特定的行终结符统一转化为\n，而写入时，又会转化为平台对应的终结符
但是该操作会破坏二级制文件中的数据，这类数据只能通过二级制模式读写</p>
<p>with关键字：优点：字句结束后，文件会正确关闭，且代码更简洁</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">with open(&#39;workfile&#39;, encoding=&#34;utf-8&#34;) as f:
</span></span><span class="line"><span class="cl">    read_data = f.read()
</span></span></code></pre></td></tr></table>
</div>
</div><p>没有with关键字，应通过f.close()关闭文件，释放资源，
若未使用close()关闭文件或者with关键字，可能导致写入的参数未写入磁盘</p>
<h3 id="721文件对象的方法">7.2.1.文件对象的方法</h3>
<p>前提：已创建f文件对象
<strong>f.read(size)：用于读取文件内容</strong>
返回值：字符串（文本模式），字节串（二进制模式）
size：可选。默认值或复数：读取整个文件内容；其他值：读取size个字符或者size个字节
到达文件末尾返回空字符串’ ‘
<strong>f.readline():从文件中读取单行字符串</strong>
保留换行符’\n&rsquo;,例如</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">f.readline()
</span></span><span class="line"><span class="cl">&#39;This is the first line of the file.\n&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>只有在文件不以换行符结尾才省略换行符
<strong>若需要读取多行，通过循环遍历整个文件对象：</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">for line in f:
</span></span><span class="line"><span class="cl">    print(line, end=&#39;&#39;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">This is the first line of the file.
</span></span><span class="line"><span class="cl">Second line of the file
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果需要以列表形式读取，则可以用list(f)或者f.readline()
<strong>f.write(string):把string内容写入文件并返回写入的字符数</strong>
写入其他类型时，要先做类型转化，转化为string或者bytes</p>
<p><strong>f.seek(offset,whence)改变文件对象的位置</strong>
通过参考点添加offset计算位置
参考点有whence指定：0：从文件开头；1：使用当前文件位置；2：使用文件末尾
默认值为0
可以和f.tell()搭配使用
在文本文件（模式字符串未使用 <code>b</code> 时打开的文件）中，只允许相对于文件开头搜索（使用 <code>seek(0, 2)</code> 搜索到文件末尾是个例外），唯一有效的 <em>offset</em> 值是能从 <code>f.tell()</code> 中返回的，或 0。其他 <em>offset</em> 值都会产生未定义的行为。</p>
<h3 id="722-使用-json-保存结构化数据">7.2.2. 使用 <a href="https://docs.python.org/zh-cn/3/library/json.html#module-json"><code>json</code></a> 保存结构化数据<a href="https://docs.python.org/zh-cn/3/tutorial/inputoutput.html#saving-structured-data-with-json">¶</a></h3>
<p>字符串可以很容易地写入文件或从文件中读取。 数字则更麻烦一些，因为 <a href="https://docs.python.org/zh-cn/3/library/io.html#io.TextIOBase.read"><code>read()</code></a> 方法只返回字符串，而字符串必须传给 <a href="https://docs.python.org/zh-cn/3/library/functions.html#int"><code>int()</code></a> 这样的函数，它接受 <code>'123'</code> 这样的字符串并返回其数值 123。 当你想要保存嵌套列表和字典等更复杂的数据类型时，手动执行解析和序列化操作将会变得非常复杂。</p>
<p>Python 允许你使用流行的数据交换格式 <a href="https://json.org/">JSON (JavaScript Object Notation)</a>，而不是让用户持续编写和调试代码来将复杂的数据类型存入文件中。 标准库模块 <a href="https://docs.python.org/zh-cn/3/library/json.html#module-json"><code>json</code></a> 可以接受带有层级结构的 Python 数据，并将其转换为字符串表示形式；这个过程称为 <em>serializing</em>。 根据字符串表示形式JSON重建数据则称为 <em>deserializing</em>。 在序列化和反序列化之间，用于代表对象的字符串可以存储在文件或数据库中，或者通过网络连接发送到远端主机。</p>
<p>备注</p>
<p>JSON 格式通常用于现代应用程序的数据交换。程序员早已对它耳熟能详，可谓是交互操作的不二之选。</p>
<p>只需一行简单的代码即可查看某个对象的 JSON 字符串表现形式：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import json
</span></span><span class="line"><span class="cl">x = [1, &#39;simple&#39;, &#39;list&#39;]
</span></span><span class="line"><span class="cl">json.dumps(x)
</span></span><span class="line"><span class="cl">&#39;[1, &#34;simple&#34;, &#34;list&#34;]&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/json.html#json.dumps"><code>dumps()</code></a> 函数还有一个变体， <a href="https://docs.python.org/zh-cn/3/library/json.html#json.dump"><code>dump()</code></a> ，它只将对象序列化为 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-text-file">text file</a> 。因此，如果 <code>f</code> 是 text file 对象，可以这样做：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">json.dump(x, f)
</span></span></code></pre></td></tr></table>
</div>
</div><p>要再次解码对象，如果 <code>f</code> 是已打开、供读取的 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-binary-file">binary file</a> 或 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-text-file">text file</a> 对象：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-gdscript3" data-lang="gdscript3"><span class="line"><span class="cl"><span class="n">x</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>备注</p>
<p>JSON 文件必须以 UTF-8 编码。当打开 JSON 文件作为一个 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-text-file">text file</a> 用于读写时，使用 <code>encoding=&quot;utf-8&quot;</code> 。</p>
<p>这种简单的序列化技术可以处理列表和字典，但在 JSON 中序列化任意类的实例，则需要付出额外努力。<a href="https://docs.python.org/zh-cn/3/library/json.html#module-json"><code>json</code></a> 模块的参考包含对此的解释。</p>
]]></content:encoded>
    </item>
    <item>
      <title>8. 错误和异常</title>
      <link>https://tuanzi-wow.cn/python/python-08-errors/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-08-errors/</guid>
      <description>语法错误与异常的区别，try/except/else/finally 的处理结构。</description>
      <content:encoded><![CDATA[<h2 id="81语法错误">8.1.语法错误</h2>
<p>又称解析错误
报错信息包括：出错的行；显示指向检测到错误位置的小箭头；文件名</p>
<h2 id="82异常">8.2.异常</h2>
<p>在执行时检测到的错误称为异常
报错信息包括：异常的类型；错误细节</p>
<h2 id="83异常的处理">8.3.异常的处理</h2>
<p>try语句的<strong>工作原理</strong>：
1.执行try子句
2.没有触发异常，跳过except子句
3.触发异常，跳过try子句剩下部分，并且将异常与except后关键字进行匹配“如果匹配，则执行except子句；如果为未匹配，则停止执行并输出一条错误信息</p>
<p><strong>特性：</strong>
一个 <code>try</code> 可以有多个普通 <code>except</code> 子句，对于一次抛出的普通异常，只有第一个匹配的 <code>except</code> 子句会执行。一个 <a href="https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except"><code>except</code></a> 子句中的类匹配的异常将是该类本身的实例或其所派生的类的实例（但反过来则不可以 &mdash; 列出派生类的 <em>except 子句</em> 不会匹配其基类的实例）
人话：基类（父类）异常可以匹配子类异常，反之不可以
so，需要主要异常匹配的顺序
<strong>异常参数</strong>
except子句可能在异常后指定一个变量（通过as），被绑定到异常实例，该实例有一个args属性，内置异常类型定义了 <a href="https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__str__"><code>__str__()</code></a> 来打印所有参数而不必显式地访问 <code>.args</code>。</p>
<p><strong>异常之间的关系</strong>
<a href="https://docs.python.org/zh-cn/3/library/exceptions.html#BaseException"><code>BaseException</code></a> 是所有异常的共同基类。它的一个子类，<a href="https://docs.python.org/zh-cn/3/library/exceptions.html#Exception"><code>Exception</code></a>，是所有非致命异常的基类。不是 <code>Exception</code> 的子类的异常通常不被处理，因为它们被用来指示程序应该终止。它们包括由 <a href="https://docs.python.org/zh-cn/3/library/sys.html#sys.exit"><code>sys.exit()</code></a> 引发的 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#SystemExit"><code>SystemExit</code></a>，以及当用户希望中断程序时引发的 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#KeyboardInterrupt"><code>KeyboardInterrupt</code></a>。</p>
<p>异常匹配的注意点：
<a href="https://docs.python.org/zh-cn/3/library/exceptions.html#Exception"><code>Exception</code></a> 可以被用作通配符，捕获（几乎）一切。然而，<strong>好的做法是，尽可能具体地说明我们打算处理的异常类型，并允许任何意外的异常传播下去。</strong></p>
<p>try&hellip;except语句具有可选的else语句</p>
<p>异常处理程序还会处理在try子句中调用的函数的异常</p>
<h3 id="84触发异常">8.4.触发异常</h3>
<p>使用raise语句，强制触发指定类型的异常
唯一的参数是要触发的异常，这个参数必须是异常实例或者异常类，如果是异常类，会隐式调用无参数的构造函数来创建一个异常实例</p>
<h3 id="85异常链">8.5.异常链</h3>
<p>raise  a from b语句来显式表明一个异常（a）是另一个异常（b）的直接后果：此处的b必须为实例或者none，而未none时，表示禁用自动异常链</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def func():
</span></span><span class="line"><span class="cl">    raise ConnectionError
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">try:
</span></span><span class="line"><span class="cl">    func()
</span></span><span class="line"><span class="cl">except ConnectionError as exc:
</span></span><span class="line"><span class="cl">    raise RuntimeError(&#39;Failed to open database&#39;) from exc
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Traceback (most recent call last):
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 2, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    func()
</span></span><span class="line"><span class="cl">    ~~~~^^
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 2, in func
</span></span><span class="line"><span class="cl">ConnectionError
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">The above exception was the direct cause of the following exception:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Traceback (most recent call last):
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 4, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    raise RuntimeError(&#39;Failed to open database&#39;) from exc
</span></span><span class="line"><span class="cl">RuntimeError: Failed to open database
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="86用户自定义异常">8.6.用户自定义异常</h3>
<p>程序可以通过创建新的异常类命名自己的异常 (Python 类的内容详见 <a href="https://docs.python.org/zh-cn/3/tutorial/classes.html#tut-classes">类</a>)。 不论是以直接还是间接的方式，异常都应从 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#Exception"><code>Exception</code></a> 类派生。</p>
<p>异常类可以被定义成能做其他类所能做的任何事，但通常应当保持简单，它往往只提供一些属性，允许相应的异常处理程序提取有关错误的信息。</p>
<p>大多数异常命名都以&quot;Error&quot;结尾，类似标准异常的命名。</p>
<p>许多标准模块定义了自己的异常，以报告他们定义的函数中可能出现的错误。</p>
<h3 id="87定义清理操作">8.7.定义清理操作</h3>
<p>try-finally语句：定义在所有情况下都要执行的操作，通常在异常处理中用于清理操作
一些复杂的触发异常场景，感觉没什么意思，自己看看吧</p>
<ul>
<li>如果执行 <code>try</code> 子句期间触发了某个异常，则某个 <a href="https://docs.python.org/zh-cn/3/reference/compound_stmts.html#except"><code>except</code></a> 子句应处理该异常。如果该异常没有 <code>except</code> 子句处理，在 <code>finally</code> 子句执行后会被重新触发。</li>
<li><code>except</code> 或 <code>else</code> 子句执行期间也会触发异常。同样，该异常会在 <code>finally</code> 子句执行之后被重新触发。</li>
<li>如果 <code>finally</code> 子句执行 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break"><code>break</code></a>、 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue"><code>continue</code></a> 或 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return"><code>return</code></a> 语句，异常不重新引发。这可能会引起混淆，因此不鼓励使用。从 3.14 版开始，编译器会为它发出一个 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#SyntaxWarning"><code>SyntaxWarning</code></a> (参见 <a href="https://peps.python.org/pep-0765/"><strong>PEP 765</strong></a>)。</li>
<li>如果执行 <code>try</code> 语句时遇到 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#break"><code>break</code></a>、<a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#continue"><code>continue</code></a> 或 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#return"><code>return</code></a> 语句，则 <code>finally</code> 子句在执行 <code>break</code>、<code>continue</code> 或 <code>return</code> 语句之前执行。</li>
<li>如果一个 <code>finally</code> 子句包含一个 <code>return</code> 语句，返回的值将是来自 <code>finally</code> 子句的 <code>return</code> 语句，而不是来自 <code>try</code> 子句的 <code>return</code> 语句。 这可能会引起混淆，因此不提倡使用。 从 3.14 版开始，编译器会为它发出一个 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#SyntaxWarning"><code>SyntaxWarning</code></a> (参见 <a href="https://peps.python.org/pep-0765/"><strong>PEP 765</strong></a>)。</li>
</ul>
<p>通常用于释放外部资源的逻辑</p>
<h3 id="88预定义的清理操作没啥意思自己看">8.8.预定义的清理操作（没啥意思，自己看）</h3>
<p>某些对象定义了不需要该对象时要执行的标准清理操作。无论使用该对象的操作是否成功，都会执行清理操作。比如，下例要打开一个文件，并输出文件内容：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">for line in open(&#34;myfile.txt&#34;):
</span></span><span class="line"><span class="cl">    print(line, end=&#34;&#34;)
</span></span></code></pre></td></tr></table>
</div>
</div><p>这个代码的问题在于，执行完代码后，文件在一段不确定的时间内处于打开状态。在简单脚本中这没有问题，但对于较大的应用程序来说可能会出问题。<a href="https://docs.python.org/zh-cn/3/reference/compound_stmts.html#with"><code>with</code></a> 语句支持以及时、正确的清理的方式使用文件对象：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">with open(&#34;myfile.txt&#34;) as f:
</span></span><span class="line"><span class="cl">    for line in f:
</span></span><span class="line"><span class="cl">        print(line, end=&#34;&#34;)
</span></span></code></pre></td></tr></table>
</div>
</div><p>语句执行完毕后，即使在处理行时遇到问题，都会关闭文件 <em>f</em>。和文件一样，支持预定义清理操作的对象会在文档中指出这一点。</p>
<h3 id="89引发和处理多个不相关的异常">8.9.引发和处理多个不相关的异常</h3>
<p>场景：继续执行收集多个错误而不是引发第一个异常
方法一：内置的 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#ExceptionGroup"><code>ExceptionGroup</code></a> 打包了一个异常实例的列表，这样它们就可以一起被引发。它本身就是一个异常，所以它可以像其他异常一样被捕获。
方法二：使用except<em>替代except，有选择地处理异常，注意此处地except</em>子句就不再是只能执行一个了</p>
<p>例子：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def f():
</span></span><span class="line"><span class="cl">    raise ExceptionGroup(
</span></span><span class="line"><span class="cl">        &#34;group1&#34;,
</span></span><span class="line"><span class="cl">        [
</span></span><span class="line"><span class="cl">            OSError(1),
</span></span><span class="line"><span class="cl">            SystemError(2),
</span></span><span class="line"><span class="cl">            ExceptionGroup(
</span></span><span class="line"><span class="cl">                &#34;group2&#34;,
</span></span><span class="line"><span class="cl">                [
</span></span><span class="line"><span class="cl">                    OSError(3),
</span></span><span class="line"><span class="cl">                    RecursionError(4)
</span></span><span class="line"><span class="cl">                ]
</span></span><span class="line"><span class="cl">            )
</span></span><span class="line"><span class="cl">        ]
</span></span><span class="line"><span class="cl">    )
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">try:
</span></span><span class="line"><span class="cl">    f()
</span></span><span class="line"><span class="cl">except* OSError as e:
</span></span><span class="line"><span class="cl">    print(&#34;There were OSErrors&#34;)
</span></span><span class="line"><span class="cl">except* SystemError as e:
</span></span><span class="line"><span class="cl">    print(&#34;There were SystemErrors&#34;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">There were OSErrors
</span></span><span class="line"><span class="cl">There were SystemErrors
</span></span><span class="line"><span class="cl">  + Exception Group Traceback (most recent call last):
</span></span><span class="line"><span class="cl">  |   File &#34;&lt;stdin&gt;&#34;, line 2, in &lt;module&gt;
</span></span><span class="line"><span class="cl">  |     f()
</span></span><span class="line"><span class="cl">  |     ~^^
</span></span><span class="line"><span class="cl">  |   File &#34;&lt;stdin&gt;&#34;, line 2, in f
</span></span><span class="line"><span class="cl">  |     raise ExceptionGroup(
</span></span><span class="line"><span class="cl">  |     ...&lt;12 lines&gt;...
</span></span><span class="line"><span class="cl">  |     )
</span></span><span class="line"><span class="cl">  | ExceptionGroup: group1 (1 sub-exception)
</span></span><span class="line"><span class="cl">  +-+---------------- 1 ----------------
</span></span><span class="line"><span class="cl">    | ExceptionGroup: group2 (1 sub-exception)
</span></span><span class="line"><span class="cl">    +-+---------------- 1 ----------------
</span></span><span class="line"><span class="cl">      | RecursionError: 4
</span></span><span class="line"><span class="cl">      +------------------------------------
</span></span></code></pre></td></tr></table>
</div>
</div><p>注意，嵌套在一个异常组中的异常必须是实例，而不是类型。这是因为在实践中，这些异常通常是那些已经被程序提出并捕获的异常</p>
<h3 id="810用注释细化异常情况">8.10.用注释细化异常情况</h3>
<p>add_note(note)用于在异常被捕获之后添加信息到异常地注释列表中
例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">try:
</span></span><span class="line"><span class="cl">    raise TypeError(&#39;bad type&#39;)
</span></span><span class="line"><span class="cl">except Exception as e:
</span></span><span class="line"><span class="cl">    e.add_note(&#39;Add some information&#39;)
</span></span><span class="line"><span class="cl">    e.add_note(&#39;Add some more information&#39;)
</span></span><span class="line"><span class="cl">    raise
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Traceback (most recent call last):
</span></span><span class="line"><span class="cl">  File &#34;&lt;stdin&gt;&#34;, line 2, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    raise TypeError(&#39;bad type&#39;)
</span></span><span class="line"><span class="cl">TypeError: bad type
</span></span><span class="line"><span class="cl">Add some information
</span></span><span class="line"><span class="cl">Add some more information
</span></span></code></pre></td></tr></table>
</div>
</div><p>应用于异常组中，例如：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def f():
</span></span><span class="line"><span class="cl">    raise OSError(&#39;operation failed&#39;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">excs = []
</span></span><span class="line"><span class="cl">for i in range(3):
</span></span><span class="line"><span class="cl">    try:
</span></span><span class="line"><span class="cl">        f()
</span></span><span class="line"><span class="cl">    except Exception as e:
</span></span><span class="line"><span class="cl">        e.add_note(f&#39;Happened in Iteration {i+1}&#39;)
</span></span><span class="line"><span class="cl">        excs.append(e)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">raise ExceptionGroup(&#39;We have some problems&#39;, excs)
</span></span><span class="line"><span class="cl">  + Exception Group Traceback (most recent call last):
</span></span><span class="line"><span class="cl">  |   File &#34;&lt;stdin&gt;&#34;, line 1, in &lt;module&gt;
</span></span><span class="line"><span class="cl">  |     raise ExceptionGroup(&#39;We have some problems&#39;, excs)
</span></span><span class="line"><span class="cl">  | ExceptionGroup: We have some problems (3 sub-exceptions)
</span></span><span class="line"><span class="cl">  +-+---------------- 1 ----------------
</span></span><span class="line"><span class="cl">    | Traceback (most recent call last):
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 3, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    |     f()
</span></span><span class="line"><span class="cl">    |     ~^^
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 2, in f
</span></span><span class="line"><span class="cl">    |     raise OSError(&#39;operation failed&#39;)
</span></span><span class="line"><span class="cl">    | OSError: operation failed
</span></span><span class="line"><span class="cl">    | Happened in Iteration 1
</span></span><span class="line"><span class="cl">    +---------------- 2 ----------------
</span></span><span class="line"><span class="cl">    | Traceback (most recent call last):
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 3, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    |     f()
</span></span><span class="line"><span class="cl">    |     ~^^
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 2, in f
</span></span><span class="line"><span class="cl">    |     raise OSError(&#39;operation failed&#39;)
</span></span><span class="line"><span class="cl">    | OSError: operation failed
</span></span><span class="line"><span class="cl">    | Happened in Iteration 2
</span></span><span class="line"><span class="cl">    +---------------- 3 ----------------
</span></span><span class="line"><span class="cl">    | Traceback (most recent call last):
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 3, in &lt;module&gt;
</span></span><span class="line"><span class="cl">    |     f()
</span></span><span class="line"><span class="cl">    |     ~^^
</span></span><span class="line"><span class="cl">    |   File &#34;&lt;stdin&gt;&#34;, line 2, in f
</span></span><span class="line"><span class="cl">    |     raise OSError(&#39;operation failed&#39;)
</span></span><span class="line"><span class="cl">    | OSError: operation failed
</span></span><span class="line"><span class="cl">    | Happened in Iteration 3
</span></span><span class="line"><span class="cl">    +------------------------------------
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>9. 类</title>
      <link>https://tuanzi-wow.cn/python/python-09-classes/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-09-classes/</guid>
      <description>名称与对象、作用域与命名空间、类的定义、继承与私有变量。</description>
      <content:encoded><![CDATA[<p>前言：
提供了把数据和功能绑定在一起的方法
支持面向对象中的多种特性：
基础机制支持多个基类;派生类能够覆盖基类的方法；类的方法能够调用基类中的同名方法
此外，还具有Python的动态特性，运行时创建，创建后可修改</p>
<h2 id="91名称和对象">9.1.名称和对象</h2>
<p>别名：对象之间相互独立，多个名称（甚至是多个作用域内的多个名称）可以绑定到同一对象。这在其他语言中通常被称为别名，这种现象主要是有益于可变对象，比如列表，，字典等等</p>
<h2 id="92python的作用域和命名空间">9.2.Python的作用域和命名空间</h2>
<h4 id="命名空间namespace">命名空间：namespace</h4>
<p>名称到对象的映射
实现：大多数靠Python字典实现
<strong>不同命名空间中的名称之间绝对没有关系</strong></p>
<h4 id="属性在点之后的名称是属性好奇怪的定义">属性：在点之后的名称是属性（好奇怪的定义）</h4>
<p>模块属性和模块中定义的全局名称之间存在直接的映射：它们共享相同的命名空间
属性可以是只读或者只写的，后一种情况可以对属性进行赋值，也可以通过del来进行删除</p>
<h4 id="命名空间的创建时间和生命周期感觉有点复杂">命名空间的创建时间和生命周期（感觉有点复杂）</h4>
<p>命名空间是在不同时刻创建的，且拥有不同的生命周期。内置名称的命名空间是在 Python 解释器启动时创建的，永远不会被删除。模块的全局命名空间在读取模块定义时创建；通常，模块的命名空间也会持续到解释器退出。从脚本文件读取或交互式读取的，由解释器顶层调用执行的语句是 <a href="https://docs.python.org/zh-cn/3/library/__main__.html#module-__main__"><code>__main__</code></a> 模块调用的一部分，也拥有自己的全局命名空间。内置名称实际上也在模块里，即 <a href="https://docs.python.org/zh-cn/3/library/builtins.html#module-builtins"><code>builtins</code></a> 。</p>
<p>函数的局部命名空间在函数被调用时被创建，并在函数返回或抛出未在函数内被处理的异常时，被删除。（实际上，用“遗忘”来描述实际发生的情况会更好一些。）当然，每次递归调用都有自己的局部命名空间。</p>
<p>一个命名空间的 <em>作用域</em> 是 Python 代码中的一段文本区域，从这个区域可直接访问该命名空间。“可直接访问”的意思是，该文本区域内的名称在被非限定引用时，查找名称的范围，是包括该命名空间在内的。</p>
<p>作用域虽然是被静态确定的，但会被动态使用。执行期间的任何时刻，都会有 3 或 4 个“命名空间可直接访问”的嵌套作用域：</p>
<ul>
<li>最内层作用域，包含局部名称，并首先在其中进行搜索</li>
<li>那些外层闭包函数的作用域，包含“非局部、非全局”的名称，从最靠内层的那个作用域开始，逐层向外搜索。</li>
<li>倒数第二层作用域，包含当前模块的全局名称</li>
<li>最外层（最后搜索）的作用域，是内置名称的命名空间</li>
</ul>
<p>如果一个名称被声明为全局，则所有引用和赋值都将直接指向“倒数第二层作用域”，即包含模块的全局名称的作用域。 要重新绑定在最内层作用域以外找到的变量，可以使用 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal"><code>nonlocal</code></a> 语句；如果未使用 nonlocal 声明，这些变量将为只读（尝试写入这样的变量将在最内层作用域中创建一个 <em>新的</em> 局部变量，而使得同名的外部变量保持不变）。</p>
<p>通常，当前局部作用域将（按字面文本）引用当前函数的局部名称。在函数之外，局部作用域引用与全局作用域一致的命名空间：模块的命名空间。 类定义在局部命名空间内再放置另一个命名空间。</p>
<p>划重点，作用域是按字面文本确定的：模块内定义的函数的全局作用域就是该模块的命名空间，无论该函数从什么地方或以什么别名被调用。另一方面，实际的名称搜索是在运行时动态完成的。但是，Python 正在朝着“编译时静态名称解析”的方向发展，因此不要过于依赖动态名称解析！（局部变量已经是被静态确定了。）</p>
<p>Python 有一个特殊规定。如果不存在生效的 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global"><code>global</code></a> 或 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal"><code>nonlocal</code></a> 语句，则对名称的赋值总是会进入最内层作用域。赋值不会复制数据，只是将名称绑定到对象。删除也是如此：语句 <code>del x</code> 从局部作用域引用的命名空间中移除对 <code>x</code> 的绑定。所有引入新名称的操作都是使用局部作用域：尤其是 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#import"><code>import</code></a> 语句和函数定义会在局部作用域中绑定模块或函数名称。</p>
<p><a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global"><code>global</code></a> 语句用于表明特定变量在全局作用域里，并应在全局作用域中重新绑定；<a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal"><code>nonlocal</code></a> 语句表明特定变量在外层作用域中，并应在外层作用域中重新绑定。</p>
<h3 id="921作用域和命名空间">9.2.1.作用域和命名空间</h3>
<p>一个经典的例子便于理解global和nonlocal对于变量绑定的影响</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def scope_test():
</span></span><span class="line"><span class="cl">    def do_local():
</span></span><span class="line"><span class="cl">        spam = &#34;local spam&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def do_nonlocal():
</span></span><span class="line"><span class="cl">        nonlocal spam
</span></span><span class="line"><span class="cl">        spam = &#34;nonlocal spam&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def do_global():
</span></span><span class="line"><span class="cl">        global spam
</span></span><span class="line"><span class="cl">        spam = &#34;global spam&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    spam = &#34;test spam&#34;
</span></span><span class="line"><span class="cl">    do_local()
</span></span><span class="line"><span class="cl">    print(&#34;After local assignment:&#34;, spam)
</span></span><span class="line"><span class="cl">    do_nonlocal()
</span></span><span class="line"><span class="cl">    print(&#34;After nonlocal assignment:&#34;, spam)
</span></span><span class="line"><span class="cl">    do_global()
</span></span><span class="line"><span class="cl">    print(&#34;After global assignment:&#34;, spam)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">scope_test()
</span></span><span class="line"><span class="cl">print(&#34;In global scope:&#34;, spam)
</span></span></code></pre></td></tr></table>
</div>
</div><p>示例代码的输出是：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">After local assignment: test spam
</span></span><span class="line"><span class="cl">After nonlocal assignment: nonlocal spam
</span></span><span class="line"><span class="cl">After global assignment: nonlocal spam
</span></span><span class="line"><span class="cl">In global scope: global spam
</span></span></code></pre></td></tr></table>
</div>
</div><p>注意，<strong>局部</strong> 赋值（这是默认状态）不会改变 <em>scope_test</em> 对 <em>spam</em> 的绑定。 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#nonlocal"><code>nonlocal</code></a> 赋值会改变 <em>scope_test</em> 对 <em>spam</em> 的绑定，而 <a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global"><code>global</code></a> 赋值会改变模块层级的绑定。</p>
<p>而且，<a href="https://docs.python.org/zh-cn/3/reference/simple_stmts.html#global"><code>global</code></a> 赋值前没有 <em>spam</em> 的绑定。</p>
<p>本人的理解：经验证是正确的，但是表述没有很准确，即函数名啥的写的比较粗略等等
首先 spam = &ldquo;test spam&quot;创建在scope_test作用域的spam，然后dolocal创建属于dolocal的spam然后do_nonlocal更新属于它外围u函数也就是socpetest的spam，然后doglobal创建全局的spam，在scope——test的每次输出都是输出属于scopetest的spam，但是最后一句 scope_test() print(&ldquo;In global scope:&rdquo;, spam) 会输出属于global的spam
此处要理解的关键就是各个作用域中的spam和  nonlocal与global对于绑定造成的影响
nonlocal是在外围函数中创建或者更新，比如此处的scope_test就是do_local等三个函数的外围函数
global则是在全局做更新或创建</p>
<h2 id="93初探类">9.3.初探类</h2>
<h3 id="931类的定义">9.3.1.类的定义</h3>
<p>class ClassName:</p>
<h3 id="932-class对象">9.3.2 Class对象</h3>
<p>支持两种操作：</p>
<h4 id="1属性引用">1.属性引用</h4>
<p>属性引用
语法：obj.name
____doc____为文档字符串属性</p>
<h4 id="2实例化">2.实例化</h4>
<p>当一个类定义了 <a href="https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__init__"><code>__init__()</code></a> 方法时，类的实例化会自动为新创建的类实例唤起 <code>__init__()</code>。 因此在这个例子中，可以通过以下语句获得一个已初始化的新实例:
当然，<a href="https://docs.python.org/zh-cn/3/reference/datamodel.html#object.__init__"><code>__init__()</code></a> 方法还有一些参数用于实现更高的灵活性。 在这种情况下，提供给类实例化运算符的参数
将被传递给 <code>__init__()</code>。 例如</p>
<h3 id="933实例对象">9.3.3.实例对象</h3>
<p>唯一操作为属性引用，引用的对象包括两个方面：函数和数据属性</p>
<h3 id="934方法对象">9.3.4.方法对象</h3>
<p>方法对象可被储存卡里
例如：xf = x.f，print（xf）
方法的特殊之处就在于实例对象会作为函数的第一个参数被传入</p>
<h3 id="935实例对象和类">9.3.5.实例对象和类</h3>
<p>正确设计实例变量和类变量</p>
<p>一般来说，实例变量<strong>用于每个实例的唯一数据</strong>，而<strong>类变量</strong>用于<strong>类的所有实例共享的属性和方法</strong>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class Dog:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    kind = &#39;canine&#39;         # 类变量被所有实例所共享
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def __init__(self, name):
</span></span><span class="line"><span class="cl">        self.name = name    # 实例变量为每个实例所独有
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d = Dog(&#39;Fido&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e = Dog(&#39;Buddy&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.kind                  # 被所有的 Dog 实例所共享
</span></span><span class="line"><span class="cl">&#39;canine&#39;
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e.kind                  # 被所有的 Dog 实例所共享
</span></span><span class="line"><span class="cl">&#39;canine&#39;
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.name                  # 为 d 所独有
</span></span><span class="line"><span class="cl">&#39;Fido&#39;
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e.name                  # 为 e 所独有
</span></span><span class="line"><span class="cl">&#39;Buddy&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>正如在 <a href="https://docs.python.org/zh-cn/3/tutorial/classes.html#tut-object">名称和对象</a> 中所讨论的，共享数据可能在涉及 <a href="https://docs.python.org/zh-cn/3/glossary.html#term-mutable">mutable</a> 对象如列表和字典时导致令人惊讶的结果。 例如，以下代码中的 <em>tricks</em> 列表不应被用作类变量因为所有 <em>Dog</em> 实例将共享一个单独的列表:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class Dog:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    tricks = []             # 类变量的错误用法
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def __init__(self, name):
</span></span><span class="line"><span class="cl">        self.name = name
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def add_trick(self, trick):
</span></span><span class="line"><span class="cl">        self.tricks.append(trick)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d = Dog(&#39;Fido&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e = Dog(&#39;Buddy&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.add_trick(&#39;roll over&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e.add_trick(&#39;play dead&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.tricks                # 非预期地被所有的 Dog 实例所共享
</span></span><span class="line"><span class="cl">[&#39;roll over&#39;, &#39;play dead&#39;]
</span></span></code></pre></td></tr></table>
</div>
</div><p>正确的类设计应该使用实例变量:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class Dog:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def __init__(self, name):
</span></span><span class="line"><span class="cl">        self.name = name
</span></span><span class="line"><span class="cl">        self.tricks = []    # 为每个 Dog 实例新建一个空列表
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def add_trick(self, trick):
</span></span><span class="line"><span class="cl">        self.tricks.append(trick)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d = Dog(&#39;Fido&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e = Dog(&#39;Buddy&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.add_trick(&#39;roll over&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e.add_trick(&#39;play dead&#39;)
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; d.tricks
</span></span><span class="line"><span class="cl">[&#39;roll over&#39;]
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; e.tricks
</span></span><span class="line"><span class="cl">[&#39;play dead&#39;]
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="94补充说明">9.4.补充说明</h2>
<p>1.同样的属性名称同时出现在类对象和实例对象时。优先选择实例对象</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">class Warehouse:
</span></span><span class="line"><span class="cl">   purpose = &#39;storage&#39;
</span></span><span class="line"><span class="cl">   region = &#39;west&#39;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">w1 = Warehouse()
</span></span><span class="line"><span class="cl">print(w1.purpose, w1.region)
</span></span><span class="line"><span class="cl">storage west
</span></span><span class="line"><span class="cl">//相当与给w2创建了一个实例属性region，要与属于warehouse的region属性区别开
</span></span><span class="line"><span class="cl">w2 = Warehouse()
</span></span><span class="line"><span class="cl">w2.region = &#39;east&#39;
</span></span><span class="line"><span class="cl">print(w2.purpose, w2.region)
</span></span><span class="line"><span class="cl">storage east
</span></span></code></pre></td></tr></table>
</div>
</div><p>方法的第一个参数常常被命名为 <code>self</code>。 这也不过就是一个约定: <code>self</code> 这一名称在 Python 中绝对没有特殊含义。 但是要注意，不遵循此约定会使得你的代码对其他 Python 程序员来说缺乏可读性，而且也可以想像一个 <em>类浏览器</em> 程序的编写可能会依赖于这样的约定。</p>
<h2 id="95-继承">9.5. 继承</h2>
<p>派生类的语法：class DeriveClassName(BaseClassName):
若基类位于另一个module，
语法为：class DerivedClassName(modname.BaseClassName):</p>
<p>关于重写：
Python 中所有的方法实际上都是 <code>virtual</code> 方法
如果想要调用基类的方法而非派生类的方法：BaseClassName.methodname(self, arguments)</p>
<p>两个有关继承机制的内置函数：
isinstancel():isinstance(obj,int) 当obj为int或者int的子类时为true；
issubclass(a,b):判断a是不是b的子类</p>
<h3 id="951多重继承">9.5.1.多重继承</h3>
<p>语法：class DerivedClassName(Base1, Base2, Base3):
多个基类访问顺序：有点复杂，自己看对于多数目的来说，在最简单的情况下，你可以认为搜索从父类所继承属性的操作是深度优先、从左到右的，当层次结构存在重叠时不会在同一个类中搜索两次。 因此，如果某个属性在 <code>DerivedClassName</code> 中找不到，就会在 <code>Base1</code> 中搜索它，然后（递归地）在 <code>Base1</code> 的基类中搜索，如果在那里也找不到，就将在 <code>Base2</code> 中搜索，依此类推。</p>
<p>真实情况比这个更复杂一些；方法解析顺序会动态改变以支持对 <a href="https://docs.python.org/zh-cn/3/library/functions.html#super"><code>super()</code></a> 的协同调用。 这种方式在某些其他多重继承型语言中被称为后续方法调用，它比单继承型语言中的 super 调用更强大。</p>
<p>动态调整顺序是有必要的，因为所有多重继承的情况都会显示出一个或更多的菱形关联（即至少有一个上级类可通过多条路径被最底层的类所访问）。 例如，所有类都是继承自 <a href="https://docs.python.org/zh-cn/3/library/functions.html#object"><code>object</code></a>，因此任何多重继承的情况都提供了一条以上的路径可以通向 <code>object</code>。 为了确保基类不会被访问一次以上，动态算法会用一种特殊方式将搜索顺序线性化，保留每个类所指定的从左至右的顺序，只调用每个上级类一次，并且保持单调性（即一个类可以被子类化而不影响其父类的优先顺序）。 总而言之，这些特性使得设计具有多重继承的可靠且可扩展的类成为可能。 要了解更多细节，请参阅 <a href="https://docs.python.org/zh-cn/3/howto/mro.html#python-2-3-mro">Python 2.3 方法解析顺序</a>。</p>
<h2 id="96私有变量">9.6.私有变量</h2>
<p>意识到：仅限从一个对象内部访问的“私有”实例变量在 Python 中并不存在
约定为：带有一个下划线的名称 (例如 <code>_spam</code>) 应该被当作是 API 的非公有部分
名称改写：任何形式为 <code>__spam</code> 的标识符（至少带有两个前缀下划线，至多一个后缀下划线）的文本将被替换为 <code>_classname__spam</code>，其中 <code>classname</code> 为去除了前缀下划线的当前类名称。</p>
<h2 id="97杂项说明">9.7.杂项说明</h2>
<p>使用datalclasses：将一些带名称的数据项捆绑在一起
from dataclasses import dataclass</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">@dataclass
</span></span><span class="line"><span class="cl">class Employee:
</span></span><span class="line"><span class="cl">    name: str
</span></span><span class="line"><span class="cl">    dept: str
</span></span><span class="line"><span class="cl">    salary: int
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="98迭代器">9.8.迭代器</h2>
<p>for语句：
原理：在容器对象调用iter（）生成一个带有&ndash;next&ndash;（）方法的迭代器对象，准一访问到末尾引发StopIteration异常来中止
通过next（）函数调用&ndash;next&ndash;（）</p>
<h2 id="99生成器">9.9.生成器</h2>
<p>一个创建迭代器的工具,返回数据时会使用yield语句</p>
<p>yield与return的区别:yield不会终结函数而是暂停函数,这正好符合生成器的需要
几个特性:
但生成器的写法更为紧凑，因为它会自动创建 <a href="https://docs.python.org/zh-cn/3/library/stdtypes.html#iterator.__iter__"><code>__iter__()</code></a> 和 <a href="https://docs.python.org/zh-cn/3/reference/expressions.html#generator.__next__"><code>__next__()</code></a> 方法。
另一个关键特性在于局部变量和执行状态会在每次调用之间自动保存。
当生成器终结时，它们还会自动引发 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#StopIteration"><code>StopIteration</code></a>。</p>
<h2 id="910生成器表达式懒得解释了自己看">9.10.生成器表达式(懒得解释了自己看)</h2>
<p>某些简单的生成器可以写成简洁的表达式代码，所用语法类似列表推导式，但外层为圆括号而非方括号。 这种表达式被设计用于生成器将立即被外层函数所使用的情况。 生成器表达式相比完整的生成器更紧凑但较不灵活，相比等效的列表推导式则更为节省内存。</p>
<p>示例:</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">sum(i*i for i in range(10))                 # sum of squares
</span></span><span class="line"><span class="cl">285
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">xvec = [10, 20, 30]
</span></span><span class="line"><span class="cl">yvec = [7, 5, 3]
</span></span><span class="line"><span class="cl">sum(x*y for x,y in zip(xvec, yvec))         # dot product
</span></span><span class="line"><span class="cl">260
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">unique_words = set(word for line in page  for word in line.split())
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">valedictorian = max((student.gpa, student.name) for student in graduates)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">data = &#39;golf&#39;
</span></span><span class="line"><span class="cl">list(data[i] for i in range(len(data)-1, -1, -1))
</span></span><span class="line"><span class="cl">[&#39;f&#39;, &#39;l&#39;, &#39;o&#39;, &#39;g&#39;]
</span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded>
    </item>
    <item>
      <title>10. 标准库概览</title>
      <link>https://tuanzi-wow.cn/python/python-10-stdlib/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-10-stdlib/</guid>
      <description>操作系统接口、文件通配符、命令行参数、错误输出重定向、字符串匹配与数字格式等常用标准库。</description>
      <content:encoded><![CDATA[<h2 id="101操作系统接口">10.1.操作系统接口</h2>
<p>import os
一定要使用import os而非from os import *
原因：防止内建的open（）函数被os.open()隐式替换掉
内置的dir（）和help（）函数可用作交互式的辅助工具</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">dir(os)
</span></span><span class="line"><span class="cl">&lt;返回由模块的所有函数组成的列表&gt;
</span></span><span class="line"><span class="cl">help(os)
</span></span><span class="line"><span class="cl">&lt;返回根据模块文档字符串创建的详细说明页面&gt;
</span></span></code></pre></td></tr></table>
</div>
</div><p>对于日常文件和目录管理任务，<strong>shutil模块</strong>提供了易用的高层级接口</p>
<h2 id="102文件通配符">10.2.文件通配符</h2>
<p><strong>glob模块</strong>提供了一个在目录中使用通配符搜索创建文件列表的函数</p>
<p>示例如下:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import glob
</span></span><span class="line"><span class="cl">glob.glob(&#39;*.py&#39;)
</span></span><span class="line"><span class="cl">[&#39;primes.py&#39;, &#39;random.py&#39;, &#39;quote.py&#39;]
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="103命令行参数">10.3.命令行参数</h2>
<p>参数是通过列表形式储存在<strong>sys模块</strong>的argv属性中
import sys来引入
<strong>argparse模块</strong><a href="https://docs.python.org/zh-cn/3/library/argparse.html#module-argparse"><code>argparse</code></a> 模块提供了一种更复杂的机制来处理命令行参数。 以下脚本可提取一个或多个文件名并可选择要显示的行数:（要用自己看）</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import argparse
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">parser = argparse.ArgumentParser(
</span></span><span class="line"><span class="cl">    prog=&#39;top&#39;,
</span></span><span class="line"><span class="cl">    description=&#39;Show top lines from each file&#39;)
</span></span><span class="line"><span class="cl">parser.add_argument(&#39;filenames&#39;, nargs=&#39;+&#39;)
</span></span><span class="line"><span class="cl">parser.add_argument(&#39;-l&#39;, &#39;--lines&#39;, type=int, default=10)
</span></span><span class="line"><span class="cl">args = parser.parse_args()
</span></span><span class="line"><span class="cl">print(args)
</span></span></code></pre></td></tr></table>
</div>
</div><p>当通过 <code>python top.py --lines=5 alpha.txt beta.txt</code> 在命令行运行时，该脚本会将 <code>args.lines</code> 设为 <code>5</code> 并将 <code>args.filenames</code> 设为 <code>['alpha.txt', 'beta.txt']</code>。</p>
<h2 id="104错误输出重定向和程序终止">10.4.错误输出重定向和程序终止</h2>
<p><strong>sys模块</strong>的stdin，stdout，stderr属性，其中stderr在发出警告和错误信息很有用
终止脚本：<strong>sys.exit()</strong></p>
<h2 id="105字符串模式匹配">10.5.字符串模式匹配</h2>
<p><strong>re模块</strong>为高级表达式提供正则表达式工具</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import re
</span></span><span class="line"><span class="cl">re.findall(r&#39;\bf[a-z]*&#39;, &#39;which foot or hand fell fastest&#39;)
</span></span><span class="line"><span class="cl">[&#39;foot&#39;, &#39;fell&#39;, &#39;fastest&#39;]
</span></span><span class="line"><span class="cl">re.sub(r&#39;(\b[a-z]+) \1&#39;, r&#39;\1&#39;, &#39;cat in the the hat&#39;)
</span></span><span class="line"><span class="cl">&#39;cat in the hat&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">&#39;tea for too&#39;.replace(&#39;too&#39;, &#39;two&#39;)
</span></span><span class="line"><span class="cl">&#39;tea for two&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>正则表达式是的，<code>yield</code> 和普通函数中的 <code>return</code> 最大的不同在于：<strong><code>yield</code> 不会让函数彻底结束，而是会让函数“暂停”，以后还能从暂停的位置继续执行。</strong></p>
<p>这就是它最特别的地方。</p>
<table>
	<thead>
			<tr>
					<th>正则</th>
					<th>含义</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><code>r''</code></td>
					<td>Python 原始字符串</td>
			</tr>
			<tr>
					<td><code>\b</code></td>
					<td>单词边界</td>
			</tr>
			<tr>
					<td><code>[a-z]</code></td>
					<td>任意一个小写字母</td>
			</tr>
			<tr>
					<td><code>*</code></td>
					<td>0 次或多次</td>
			</tr>
			<tr>
					<td><code>+</code></td>
					<td>1 次或多次</td>
			</tr>
			<tr>
					<td><code>()</code></td>
					<td>捕获组</td>
			</tr>
			<tr>
					<td><code>\1</code></td>
					<td>引用第一个捕获组</td>
			</tr>
			<tr>
					<td><code>findall()</code></td>
					<td>找出所有匹配内容</td>
			</tr>
			<tr>
					<td><code>sub()</code></td>
					<td>查找并替换</td>
			</tr>
	</tbody>
</table>
<h2 id="106数字">10.6.数字</h2>
<p>math模块：众多数学方法
random：随机选择工具
statistics：计算数值数据的基本统计属性：例如均值，中位数，方差等等</p>
<h2 id="107互联网访问">10.7.互联网访问</h2>
<p>挺多的，最简单的两个
<a href="https://docs.python.org/zh-cn/3/library/urllib.request.html#module-urllib.request"><code>urllib.request</code></a> 用于从URL检索数据，以及 <a href="https://docs.python.org/zh-cn/3/library/smtplib.html#module-smtplib"><code>smtplib</code></a> 用于发送邮件</p>
<h2 id="108日期和时间">10.8.日期和时间</h2>
<p>datatime模块</p>
<h2 id="109数据压缩">10.9.数据压缩</h2>
<p>常见的数据存档和压缩格式由模块直接支持，包括：<a href="https://docs.python.org/zh-cn/3/library/zlib.html#module-zlib"><code>zlib</code></a>, <a href="https://docs.python.org/zh-cn/3/library/gzip.html#module-gzip"><code>gzip</code></a>, <a href="https://docs.python.org/zh-cn/3/library/bz2.html#module-bz2"><code>bz2</code></a>, <a href="https://docs.python.org/zh-cn/3/library/lzma.html#module-lzma"><code>lzma</code></a>, <a href="https://docs.python.org/zh-cn/3/library/zipfile.html#module-zipfile"><code>zipfile</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/tarfile.html#module-tarfile"><code>tarfile</code></a></p>
<h2 id="1010性能测试">10.10.性能测试</h2>
<h2 id="1010-性能测量">10.10. 性能测量</h2>
<p>一些 Python 用户对了解同一问题的不同方法的相对性能产生了浓厚的兴趣。Python 提供了一种可以立即回答这些问题的测量工具。</p>
<p>例如，元组封包和拆包功能相比传统的交换参数可能更具吸引力。<a href="https://docs.python.org/zh-cn/3/library/timeit.html#module-timeit"><code>timeit</code></a> 模块可以快速演示在运行效率方面一定的优势:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from timeit import Timer
</span></span><span class="line"><span class="cl">Timer(&#39;t=a; a=b; b=t&#39;, &#39;a=1; b=2&#39;).timeit()
</span></span><span class="line"><span class="cl">0.57535828626024577
</span></span><span class="line"><span class="cl">Timer(&#39;a,b = b,a&#39;, &#39;a=1; b=2&#39;).timeit()
</span></span><span class="line"><span class="cl">0.54962537085770791
</span></span></code></pre></td></tr></table>
</div>
</div><p>与 <a href="https://docs.python.org/zh-cn/3/library/timeit.html#module-timeit"><code>timeit</code></a> 的精细粒度级别相反， <a href="https://docs.python.org/zh-cn/3/library/profile.html#module-profile"><code>profile</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/profile.html#module-pstats"><code>pstats</code></a> 模块提供了用于在较大的代码块中识别时间关键部分的工具。</p>
<h2 id="1011质量控制写测试">10.11.质量控制（写测试）</h2>
<p>这个感觉会有点用</p>
<p>开发高质量软件的一种方法是在开发过程中为每个函数编写测试，并在开发过程中经常运行这些测试。</p>
<p><a href="https://docs.python.org/zh-cn/3/library/doctest.html#module-doctest"><code>doctest</code></a> 模块提供了一个工具，用于扫描模块并验证程序文档字符串中嵌入的测试。测试构造就像将典型调用及其结果剪切并粘贴到文档字符串一样简单。这通过向用户提供示例来改进文档，并且它允许 doctest 模块确保代码与文档保持一致:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">def average(values):
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;计算数字列表的算术平均值
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    &gt;&gt;&gt; print(average([20, 30, 70]))
</span></span><span class="line"><span class="cl">    40.0
</span></span><span class="line"><span class="cl">    &#34;&#34;&#34;
</span></span><span class="line"><span class="cl">    return sum(values) / len(values)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">import doctest
</span></span><span class="line"><span class="cl">doctest.testmod()   # 自动验证嵌入式测试
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/unittest.html#module-unittest"><code>unittest</code></a> 模块不像 <a href="https://docs.python.org/zh-cn/3/library/doctest.html#module-doctest"><code>doctest</code></a> 模块那样易于使用，但它允许在一个单独的文件中维护更全面的测试集:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import unittest
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">class TestStatisticalFunctions(unittest.TestCase):
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def test_average(self):
</span></span><span class="line"><span class="cl">        self.assertEqual(average([20, 30, 70]), 40.0)
</span></span><span class="line"><span class="cl">        self.assertEqual(round(average([1, 5, 7]), 1), 4.3)
</span></span><span class="line"><span class="cl">        with self.assertRaises(ZeroDivisionError):
</span></span><span class="line"><span class="cl">            average([])
</span></span><span class="line"><span class="cl">        with self.assertRaises(TypeError):
</span></span><span class="line"><span class="cl">            average(20, 30, 70)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">unittest.main()  # 从命令行调用时会执行所有测试
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="1012内置电池">10.12.内置电池</h2>
<p>Python 有&quot;自带电池&quot;的理念。通过其包的复杂和强大功能可以最好地看到这一点。例如:</p>
<ul>
<li><a href="https://docs.python.org/zh-cn/3/library/xmlrpc.client.html#module-xmlrpc.client"><code>xmlrpc.client</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/xmlrpc.server.html#module-xmlrpc.server"><code>xmlrpc.server</code></a> 模块使得实现远程过程调用变成了小菜一碟。 尽管存在于模块名称中，但用户不需要直接了解或处理 XML。</li>
<li><a href="https://docs.python.org/zh-cn/3/library/email.html#module-email"><code>email</code></a> 包是一个用于管理电子邮件消息的库，包括 MIME 和其他基于 <a href="https://datatracker.ietf.org/doc/html/rfc5322.html"><strong>RFC 5322</strong></a> 的消息文档。 不同于实际发送和接收消息的 <a href="https://docs.python.org/zh-cn/3/library/smtplib.html#module-smtplib"><code>smtplib</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/poplib.html#module-poplib"><code>poplib</code></a>，email 包提供用于构建或解码复杂消息结构（包括附件）以及实现互联网编码格式和标头协议的完整工具集。</li>
<li><a href="https://docs.python.org/zh-cn/3/library/json.html#module-json"><code>json</code></a> 包为解析这种流行的数据交换格式提供了强大的支持。 <a href="https://docs.python.org/zh-cn/3/library/csv.html#module-csv"><code>csv</code></a> 模块支持以逗号分隔值格式直接读取和写入文件，这种格式通常为数据库和电子表格所支持。 XML 处理由 <a href="https://docs.python.org/zh-cn/3/library/xml.etree.elementtree.html#module-xml.etree.ElementTree"><code>xml.etree.ElementTree</code></a> ， <a href="https://docs.python.org/zh-cn/3/library/xml.dom.html#module-xml.dom"><code>xml.dom</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/xml.sax.html#module-xml.sax"><code>xml.sax</code></a> 包支持。这些模块和软件包共同大大简化了 Python 应用程序和其他工具之间的数据交换。</li>
<li><a href="https://docs.python.org/zh-cn/3/library/sqlite3.html#module-sqlite3"><code>sqlite3</code></a> 模块是 SQLite 数据库库的包装器，提供了一个可以使用稍微非标准的 SQL 语法更新和访问的持久数据库。</li>
<li>国际化由许多模块支持，包括 <a href="https://docs.python.org/zh-cn/3/library/gettext.html#module-gettext"><code>gettext</code></a> ， <a href="https://docs.python.org/zh-cn/3/library/locale.html#module-locale"><code>locale</code></a> ，以及 <a href="https://docs.python.org/zh-cn/3/library/codecs.html#module-codecs"><code>codecs</code></a> 包。</li>
</ul>
<h2 id="11-标准库概览--第二部分">11. 标准库概览 · 第二部分</h2>
<h2 id="111输出的格式化">11.1.输出的格式化</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/reprlib.html#module-reprlib"><code>reprlib</code></a> 模块提供了一个定制化版本的 <a href="https://docs.python.org/zh-cn/3/library/functions.html#repr"><code>repr()</code></a> 函数，用于缩略显示大型或深层嵌套的容器对象
<a href="https://docs.python.org/zh-cn/3/library/pprint.html#module-pprint"><code>pprint</code></a> 模块提供了更加复杂的打印控制，其输出的内置对象和用户自定义对象能够被解释器直接读取。当输出结果过长而需要折行时，“美化输出机制”会添加换行符和缩进，以更清楚地展示数据结构:
<a href="https://docs.python.org/zh-cn/3/library/textwrap.html#module-textwrap"><code>textwrap</code></a> 模块能够格式化文本段落，以适应给定的屏幕宽度:
<a href="https://docs.python.org/zh-cn/3/library/locale.html#module-locale"><code>locale</code></a> 模块处理与特定地域文化相关的数据格式。locale 模块的 format 函数包含一个 grouping 属性，可直接将数字格式化为带有组分隔符的样式:</p>
<h2 id="112模块">11.2.模块</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/string.html#module-string"><code>string</code></a> 模块包含一个通用的 <a href="https://docs.python.org/zh-cn/3/library/string.html#string.Template"><code>Template</code></a> 类，具有适用于最终用户的简化语法。它允许用户在不更改应用逻辑的情况下定制自己的应用。</p>
<p>上述格式化操作是通过占位符实现的，占位符由 <code>$</code> 加上合法的 Python 标识符（只能包含字母、数字和下划线）构成。一旦使用花括号将占位符括起来，就可以在后面直接跟上更多的字母和数字而无需空格分割。<code>$$</code> 将被转义成单个字符 <code>$</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from string import Template
</span></span><span class="line"><span class="cl">t = Template(&#39;${village}folk send $$10 to $cause.&#39;)
</span></span><span class="line"><span class="cl">t.substitute(village=&#39;Nottingham&#39;, cause=&#39;the ditch fund&#39;)
</span></span><span class="line"><span class="cl">&#39;Nottinghamfolk send $10 to the ditch fund.&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果在字典或关键字参数中未提供某个占位符的值，那么 <a href="https://docs.python.org/zh-cn/3/library/string.html#string.Template.substitute"><code>substitute()</code></a> 方法将抛出 <a href="https://docs.python.org/zh-cn/3/library/exceptions.html#KeyError"><code>KeyError</code></a>。对于邮件合并类型的应用，用户提供的数据有可能是不完整的，此时使用 <a href="https://docs.python.org/zh-cn/3/library/string.html#string.Template.safe_substitute"><code>safe_substitute()</code></a> 方法更加合适 —— 如果数据缺失，它会直接将占位符原样保留。</p>
<h2 id="113操作二进制数据记录布局">11.3.操作二进制数据记录布局</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/struct.html#module-struct"><code>struct</code></a> 模块提供了 <a href="https://docs.python.org/zh-cn/3/library/struct.html#struct.pack"><code>pack()</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/struct.html#struct.unpack"><code>unpack()</code></a> 函数，用于处理不定长度的二进制记录格式。</p>
<h2 id="114-多线程之前学java有点学吐了">11.4. 多线程（之前学JAVA有点学吐了）</h2>
<p>线程是一种对于非顺序依赖的多个任务进行解耦的技术。多线程可以提高应用的响应效率，当接收用户输入的同时，保持其他任务在后台运行。一个有关的应用场景是，将 I/O 和计算运行在两个并行的线程中。</p>
<p>以下代码展示了高阶的 <a href="https://docs.python.org/zh-cn/3/library/threading.html#module-threading"><code>threading</code></a> 模块如何在后台运行任务，且不影响主程序的继续运行:</p>
<p>Copy</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import threading, zipfile
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">class AsyncZip(threading.Thread):
</span></span><span class="line"><span class="cl">    def __init__(self, infile, outfile):
</span></span><span class="line"><span class="cl">        super().__init__()
</span></span><span class="line"><span class="cl">        self.infile = infile
</span></span><span class="line"><span class="cl">        self.outfile = outfile
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    def run(self):
</span></span><span class="line"><span class="cl">        with zipfile.ZipFile(self.outfile, &#39;w&#39;, zipfile.ZIP_DEFLATED) as f:
</span></span><span class="line"><span class="cl">            f.write(self.infile)
</span></span><span class="line"><span class="cl">        print(&#39;Finished background zip of:&#39;, self.infile)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">background = AsyncZip(&#39;mydata.txt&#39;, &#39;myarchive.zip&#39;)
</span></span><span class="line"><span class="cl">background.start()
</span></span><span class="line"><span class="cl">print(&#39;The main program continues to run in foreground.&#39;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">background.join()    # 等待后台任务结束
</span></span><span class="line"><span class="cl">print(&#39;Main program waited until background was done.&#39;)
</span></span></code></pre></td></tr></table>
</div>
</div><p>多线程应用面临的主要挑战是，相互协调的多个线程之间需要共享数据或其他资源。为此，threading 模块提供了多个同步操作原语，包括线程锁、事件、条件变量和信号量。</p>
<p>尽管这些工具非常强大，但微小的设计错误却可以导致一些难以复现的问题。因此，实现多任务协作的首选方法是将所有对资源的请求集中到一个线程中，然后使用 <a href="https://docs.python.org/zh-cn/3/library/queue.html#module-queue"><code>queue</code></a> 模块向该线程供应来自其他线程的请求。 应用程序使用 <a href="https://docs.python.org/zh-cn/3/library/queue.html#queue.Queue"><code>Queue</code></a> 对象进行线程间通信和协调，更易于设计，更易读，更可靠。</p>
<h2 id="115日志记录">11.5.日志记录</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/logging.html#module-logging"><code>logging</code></a> 模块提供功能齐全且灵活的日志记录系统,在最简单的情况下，日志消息被发送到文件或 <code>sys.stderr</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import logging
</span></span><span class="line"><span class="cl">logging.debug(&#39;Debugging information&#39;)
</span></span><span class="line"><span class="cl">logging.info(&#39;Informational message&#39;)
</span></span><span class="line"><span class="cl">logging.warning(&#39;Warning:config file %s not found&#39;, &#39;server.conf&#39;)
</span></span><span class="line"><span class="cl">logging.error(&#39;Error occurred&#39;)
</span></span><span class="line"><span class="cl">logging.critical(&#39;Critical error -- shutting down&#39;)
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="116弱引用这个在java的gc相关部分貌似也有">11.6.弱引用（这个在JAVA的GC相关部分貌似也有）</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/weakref.html#module-weakref"><code>weakref</code></a> 模块提供的工具可以不必创建引用就能跟踪对象。 当对象不再需要时，它将自动从一个弱引用表中被移除，并为弱引用对象触发一个回调。 典型应用包括对创建开销较大的对象进行缓存</p>
<h2 id="117操作列表的工具懒得看要用的时候自然会查">11.7.操作列表的工具（懒得看，要用的时候自然会查）</h2>
<p>许多对于数据结构的需求可以通过内置列表类型来满足。 但是，有时也会需要具有不同效费比的替代实现。</p>
<p><a href="https://docs.python.org/zh-cn/3/library/array.html#module-array"><code>array</code></a> 模块提供了一种 <a href="https://docs.python.org/zh-cn/3/library/array.html#array.array"><code>array</code></a> 对象，它类似于列表，但只能存储类型一致的数据且存储密度更高。 下面的例子显示了一个由存储为双字节无符号整数的数字 (类型码 <code>&quot;H&quot;</code>) 组成的元组，而不是常规 Python int 对象列表所采用的每个条目 16 字节:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from array import array
</span></span><span class="line"><span class="cl">a = array(&#39;H&#39;, [4000, 10, 700, 22222])
</span></span><span class="line"><span class="cl">sum(a)
</span></span><span class="line"><span class="cl">26932
</span></span><span class="line"><span class="cl">a[1:3]
</span></span><span class="line"><span class="cl">array(&#39;H&#39;, [10, 700])
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/collections.html#module-collections"><code>collections</code></a> 模块提供了一种 <a href="https://docs.python.org/zh-cn/3/library/collections.html#collections.deque"><code>deque</code></a> 对象，它类似于列表，但从左端添加和弹出的速度较快而在中间查找的速度较慢。 此种对象适用于实现队列和广度优先树搜索:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from collections import deque
</span></span><span class="line"><span class="cl">d = deque([&#34;task1&#34;, &#34;task2&#34;, &#34;task3&#34;])
</span></span><span class="line"><span class="cl">d.append(&#34;task4&#34;)
</span></span><span class="line"><span class="cl">print(&#34;Handling&#34;, d.popleft())
</span></span><span class="line"><span class="cl">Handling task1
</span></span><span class="line"><span class="cl">unsearched = deque([starting_node])
</span></span><span class="line"><span class="cl">def breadth_first_search(unsearched):
</span></span><span class="line"><span class="cl">    node = unsearched.popleft()
</span></span><span class="line"><span class="cl">    for m in gen_moves(node):
</span></span><span class="line"><span class="cl">        if is_goal(m):
</span></span><span class="line"><span class="cl">            return m
</span></span><span class="line"><span class="cl">        unsearched.append(m)
</span></span></code></pre></td></tr></table>
</div>
</div><p>在替代的列表实现以外，标准库也提供了其他工具，例如 <a href="https://docs.python.org/zh-cn/3/library/bisect.html#module-bisect"><code>bisect</code></a> 模块具有用于操作有序列表的函数:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">import bisect
</span></span><span class="line"><span class="cl">scores = [(100, &#39;perl&#39;), (200, &#39;tcl&#39;), (400, &#39;lua&#39;), (500, &#39;python&#39;)]
</span></span><span class="line"><span class="cl">bisect.insort(scores, (300, &#39;ruby&#39;))
</span></span><span class="line"><span class="cl">scores
</span></span><span class="line"><span class="cl">[(100, &#39;perl&#39;), (200, &#39;tcl&#39;), (300, &#39;ruby&#39;), (400, &#39;lua&#39;), (500, &#39;python&#39;)]
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/heapq.html#module-heapq"><code>heapq</code></a> 模块提供了基于常规列表来实现堆的函数。 最小值的条目总是保持在位置零。 这对于需要重复访问最小元素而不希望运行完整列表排序的应用来说非常有用:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from heapq import heapify, heappop, heappush
</span></span><span class="line"><span class="cl">data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
</span></span><span class="line"><span class="cl">heapify(data)                      # 将列表重新调整为堆顺序
</span></span><span class="line"><span class="cl">heappush(data, -5)                 # 添加一个新条目
</span></span><span class="line"><span class="cl">[heappop(data) for i in range(3)]  # 获取三个最小的条目
</span></span><span class="line"><span class="cl">[-5, 0, 1]
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="118十进制浮点算法">11.8.十进制浮点算法</h2>
<p><a href="https://docs.python.org/zh-cn/3/library/decimal.html#module-decimal"><code>decimal</code></a> 模块提供了一种 <a href="https://docs.python.org/zh-cn/3/library/decimal.html#decimal.Decimal"><code>Decimal</code></a> 数据类型用于十进制浮点运算。 相比内置的 <a href="https://docs.python.org/zh-cn/3/library/functions.html#float"><code>float</code></a> 二进制浮点实现，该类特别适用于
这个算有点用</p>
<ul>
<li>财务应用和其他需要精确十进制表示的用途，</li>
<li><strong>控制精度，</strong></li>
<li>控制四舍五入以满足法律或监管要求，</li>
<li><strong>跟踪有效小数位，或</strong></li>
<li>用户期望结果与手工完成的计算相匹配的应用程序。</li>
</ul>
<p><a href="https://docs.python.org/zh-cn/3/library/decimal.html#decimal.Decimal"><code>Decimal</code></a> 表示的结果会保留尾部的零，并根据具有两个有效位的被乘数自动推出四个有效位。 Decimal 可以模拟手工运算来避免当二进制浮点数无法精确表示十进制数时会导致的问题。</p>
]]></content:encoded>
    </item>
    <item>
      <title>12. 虚拟环境和包</title>
      <link>https://tuanzi-wow.cn/python/python-12-venv/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-12-venv/</guid>
      <description>为什么需要虚拟环境，venv 的创建与激活，pip 管理依赖包。</description>
      <content:encoded><![CDATA[<h2 id="121概述">12.1概述</h2>
<p>使用不存在标准库的软件包和模块
需要特定的库</p>
<p>解决方法1：创建一个虚拟环境（virtual environment):一个目录树，安装有特定版本的Python版本，以及许多其他包</p>
<h2 id="122创建虚拟环境">12.2.创建虚拟环境</h2>
<p>用于创建虚拟环境的模块：venv
例如：python -m venv tutorial-env
虚拟环境的常见目录为.venv，通常会被隐藏
激活该虚拟环境的语句：tutorial-env\Scripts\activate
撤销激活一个虚拟环境
激活的虚拟环境并不会以任何方式改变PYTHONPATH；最佳实践实在bash中执行unset PYTHONPATH</p>
<h2 id="123使用pip管理包">12.3.使用pip管理包</h2>
<p>作用：安装升级，移除软件包
默认情况下pip或从Python Package Index安装软件包
完整的用法请查阅</p>
]]></content:encoded>
    </item>
    <item>
      <title>15. 浮点算术：问题和限制</title>
      <link>https://tuanzi-wow.cn/python/python-15-float/</link>
      <pubDate>Fri, 04 Sep 2026 00:00:00 +0800</pubDate>
      <guid>https://tuanzi-wow.cn/python/python-15-float/</guid>
      <description>二进制浮点数为什么表示不了某些小数，以及舍入误差的处理思路。</description>
      <content:encoded><![CDATA[<p>情景：
0.1永远无法用以2为基底的小数，他是一个无限循环小数
0.0001100110011001100110011001100110011001100110011&hellip;
你只能得到一个近似值
比较有意思的一个点：
1/10 = 0.1 貌似是存储的精确值，但是实际上只是存储的最接近0.1的计算机可表示的二进制分数
于此同时，有许多额十进制数共享该最接近的二进制分数
比如： <code>0.1</code> 、 <code>0.10000000000000001</code> 、 <code>0.1000000000000000055511151231257827021181583404541015625</code> 全都近似于 <code>3602879701896397 / 2 ** 55</code>
如果想要美观的输出，可以通过字符串格式化限定输出的位数</p>
<p>还有一个有趣的现象
0.1 + 0.1 + 0.1 == 0.3为False
这个原理就是上述
但是捏
如果一定要进行不精确表达，可以使用math.isclose()</p>
<h3 id="but">BUT！</h3>
<p>正如那篇文章的结尾所言，“对此问题并无简单的答案。” 但是也不必过于担心浮点数的问题！ Python 浮点运算中的错误是从浮点运算硬件继承而来，而在大多数机器上每次浮点运算的误差不超过 2**53 分之一。 这对大多数任务来说都已足够，但你确实需要记住它并非十进制算术，且每次浮点运算都可能会导致新的舍入错误。</p>
<p>而如果想要进行精确的十进制模块的计算，尝试使用decimal模块或者fractions模块
还有很多模块，但是我懒得赘述了
自己看看吧</p>
<h2 id="151表示性错误">15.1.表示性错误</h2>
<p>定义：指的是某些十进制小数无法以二进制精确表示这一事实造成的失误本小节将详细解释 &ldquo;0.1&rdquo; 的例子，并说明你可以怎样亲自对此类情况进行精确分析。 假定前提是已基本熟悉二进制浮点表示法。</p>
<p><em>表示性错误</em> 是指某些（其实是大多数）十进制小数无法以二进制（以 2 为基数的计数制）精确表示这一事实造成的错误。 这就是为什么 Python（或者 Perl、C、C++、Java、Fortran 以及许多其他语言）经常不会显示你所期待的精确十进制数值的主要原因。</p>
<p>为什么会这样？ 1/10 是无法用二进制小数精确表示的。 至少从 2000 年起，几乎所有机器都使用 IEEE 754 二进制浮点运算标准，而几乎所有系统平台都将 Python 浮点数映射为 IEEE 754 binary64 &ldquo;双精度&rdquo; 值。 IEEE 754 binary64 值包含 53 位精度，因此在输入时计算机会尽量将 0.1 转换为以 <em>J</em>/2**<em>N</em> 形式所能表示的最接近的小数，其中 <em>J</em> 为恰好包含 53 比特位的整数。 重新将</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">1 / 10 ~= J / (2**N)
</span></span></code></pre></td></tr></table>
</div>
</div><p>写为</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">J ~= 2**N / 10
</span></span></code></pre></td></tr></table>
</div>
</div><p>并且由于 <em>J</em> 恰好有 53 位 (即 <code>&gt;= 2**52</code> 但 <code>&lt; 2**53</code>)，<em>N</em> 的最佳值为 56:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">2**52 &lt;=  2**56 // 10  &lt; 2**53
</span></span><span class="line"><span class="cl">True
</span></span></code></pre></td></tr></table>
</div>
</div><p>也就是说，56 是唯一能使 <em>J</em> 恰好有 53 位的 <em>N</em> 值。 这样 <em>J</em> 可能的最佳就是舍入之后的商:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">q, r = divmod(2**56, 10)
</span></span><span class="line"><span class="cl">r
</span></span><span class="line"><span class="cl">6
</span></span></code></pre></td></tr></table>
</div>
</div><p>由于余数超过 10 的一半，所以最佳近似值可通过向上舍入获得:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">q+1
</span></span><span class="line"><span class="cl">7205759403792794
</span></span></code></pre></td></tr></table>
</div>
</div><p>因此在 IEEE 754 双精度下可能达到的 1/10 的最佳近似值为:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">7205759403792794 / 2 ** 56
</span></span></code></pre></td></tr></table>
</div>
</div><p>分子和分母都除以二则结果小数为:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">3602879701896397 / 2 ** 55
</span></span></code></pre></td></tr></table>
</div>
</div><p>请注意由于我们做了向上舍入，这个结果实际上略大于 1/10；如果我们没有向上舍入，则商将会略小于 1/10。 但无论如何它都不会是 <em>精确的</em> 1/10！</p>
<p>因此计算机永远不会 &ldquo;看到&rdquo; 1/10: 它实际看到的就是上面所给出的小数，即它能达到的最佳 IEEE 754 双精度近似值:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">0.1 * 2 ** 55
</span></span><span class="line"><span class="cl">3602879701896397.0
</span></span></code></pre></td></tr></table>
</div>
</div><p>如果我们将该小数乘以 10**55，我们可以看到该值输出 55 个十进制数位:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">3602879701896397 * 10 ** 55 // 2 ** 55
</span></span><span class="line"><span class="cl">1000000000000000055511151231257827021181583404541015625
</span></span></code></pre></td></tr></table>
</div>
</div><p>这意味着存储在计算机中的确切数字等于十进制数值 0.1000000000000000055511151231257827021181583404541015625。 许多语言（包括较旧版本的 Python）都不会显示这个完整的十进制数值，而是将结果舍入到 17 位有效数字:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">format(0.1, &#39;.17f&#39;)
</span></span><span class="line"><span class="cl">&#39;0.10000000000000001&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="https://docs.python.org/zh-cn/3/library/fractions.html#module-fractions"><code>fractions</code></a> 和 <a href="https://docs.python.org/zh-cn/3/library/decimal.html#module-decimal"><code>decimal</code></a> 模块使得这样的计算更为容易:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">from decimal import Decimal
</span></span><span class="line"><span class="cl">from fractions import Fraction
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Fraction.from_float(0.1)
</span></span><span class="line"><span class="cl">Fraction(3602879701896397, 36028797018963968)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">(0.1).as_integer_ratio()
</span></span><span class="line"><span class="cl">(3602879701896397, 36028797018963968)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Decimal.from_float(0.1)
</span></span><span class="line"><span class="cl">Decimal(&#39;0.1000000000000000055511151231257827021181583404541015625&#39;)
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">format(Decimal.from_float(0.1), &#39;.17&#39;)
</span></span><span class="line"><span class="cl">&#39;0.10000000000000001&#39;
</span></span></code></pre></td></tr></table>
</div>
</div><p>自己看看吧，讲得还是挺清楚的</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
