Files
hustoj/web/python-docs/tutorial/modules.html
2025-03-09 17:10:56 +08:00

612 lines
60 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>6. 模块 &#8212; Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="../_static/translations.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="在 Python 3.8.20 文档 中搜索"
href="../_static/opensearch.xml"/>
<link rel="author" title="关于这些文档" href="../about.html" />
<link rel="index" title="索引" href="../genindex.html" />
<link rel="search" title="搜索" href="../search.html" />
<link rel="copyright" title="版权所有" href="../copyright.html" />
<link rel="next" title="7. 输入与输出" href="inputoutput.html" />
<link rel="prev" title="5. 数据结构" href="datastructures.html" />
<link rel="canonical" href="https://docs.python.org/3/tutorial/modules.html" />
<style>
@media only screen {
table.full-width-table {
width: 100%;
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="快速搜索"/>
<input type="submit" value="转向"/>
</form>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">6. 模块</a><ul>
<li><a class="reference internal" href="#more-on-modules">6.1. 模块详解</a><ul>
<li><a class="reference internal" href="#executing-modules-as-scripts">6.1.1. 以脚本方式执行模块</a></li>
<li><a class="reference internal" href="#the-module-search-path">6.1.2. 模块搜索路径</a></li>
<li><a class="reference internal" href="#compiled-python-files">6.1.3. “已编译的” Python 文件</a></li>
</ul>
</li>
<li><a class="reference internal" href="#standard-modules">6.2. 标准模块</a></li>
<li><a class="reference internal" href="#the-dir-function">6.3. <code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code> 函数</a></li>
<li><a class="reference internal" href="#packages">6.4. 包</a><ul>
<li><a class="reference internal" href="#importing-from-a-package">6.4.1. 从包中导入 *</a></li>
<li><a class="reference internal" href="#intra-package-references">6.4.2. 相对导入</a></li>
<li><a class="reference internal" href="#packages-in-multiple-directories">6.4.3. 多目录中的包</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="datastructures.html"
title="上一章"><span class="section-number">5. </span>数据结构</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="inputoutput.html"
title="下一章"><span class="section-number">7. </span>输入与输出</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/tutorial/modules.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
这个文档所针对的是一个已不再受支持的 Python 旧版本。
你应当升级版本,并阅读
<a href="/3/tutorial/modules.html"> Python 当前稳定版本的文档</a>.
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
accesskey="I">索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="inputoutput.html" title="7. 输入与输出"
accesskey="N">下一页</a> |</li>
<li class="right" >
<a href="datastructures.html" title="5. 数据结构"
accesskey="P">上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python 教程</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="modules">
<span id="tut-modules"></span><h1><span class="section-number">6. </span>模块<a class="headerlink" href="#modules" title="永久链接至标题"></a></h1>
<p>退出 Python 解释器后,再次进入时,之前在 Python 解释器中定义的函数和变量就丢失了。因此,编写较长程序时,最好用文本编辑器代替解释器,执行文件中的输入内容,这就是编写 <em>脚本</em> 。随着程序越来越长,为了方便维护,最好把脚本拆分成多个文件。编写脚本还一个好处,不同程序调用同一个函数时,不用把函数定义复制到各个程序。</p>
<p>为实现这些需求Python 把各种定义存入一个文件,在脚本或解释器的交互式实例中使用。这个文件就是 <em>模块</em> ;模块中的定义可以 <em>导入</em> 到其他模块或 <em></em> 模块(在顶层和计算器模式下,执行脚本中可访问的变量集)。</p>
<p>模块是包含 Python 定义和语句的文件。其文件名是模块名加后缀名 <code class="file docutils literal notranslate"><span class="pre">.py</span></code> 。在模块内部,通过全局变量 <code class="docutils literal notranslate"><span class="pre">__name__</span></code> 可以获取模块名(即字符串)。例如,用文本编辑器在当前目录下创建 <code class="file docutils literal notranslate"><span class="pre">fibo.py</span></code> 文件,输入以下内容:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Fibonacci numbers module</span>
<span class="k">def</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># write Fibonacci series up to n</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">&#39; &#39;</span><span class="p">)</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span>
<span class="nb">print</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">fib2</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> <span class="c1"># return Fibonacci series up to n</span>
<span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">n</span><span class="p">:</span>
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span><span class="o">+</span><span class="n">b</span>
<span class="k">return</span> <span class="n">result</span>
</pre></div>
</div>
<p>现在,进入 Python 解释器,用以下命令导入该模块:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
</pre></div>
</div>
<p>这项操作不直接把 <code class="docutils literal notranslate"><span class="pre">fibo</span></code> 函数定义的名称导入到当前符号表,只导入模块名 <code class="docutils literal notranslate"><span class="pre">fibo</span></code> 。要使用模块名访问函数:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="n">fib</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="n">fib2</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="go">[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fibo</span><span class="o">.</span><span class="vm">__name__</span>
<span class="go">&#39;fibo&#39;</span>
</pre></div>
</div>
<p>如果经常使用某个函数,可以把它赋值给局部变量:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span> <span class="o">=</span> <span class="n">fibo</span><span class="o">.</span><span class="n">fib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<section id="more-on-modules">
<span id="tut-moremodules"></span><h2><span class="section-number">6.1. </span>模块详解<a class="headerlink" href="#more-on-modules" title="永久链接至标题"></a></h2>
<p>模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 <em>第一次</em> 遇到模块名时执行。<a class="footnote-reference brackets" href="#id2" id="id1">1</a> (文件作为脚本运行时,也会执行这些语句。)</p>
<p>模块有自己的私有符号表,用作模块中所有函数的全局符号表。因此,在模块内使用全局变量时,不用担心与用户定义的全局变量发生冲突。另一方面,可以用与访问模块函数一样的标记法,访问模块的全局变量,<code class="docutils literal notranslate"><span class="pre">modname.itemname</span></code></p>
<p>可以把其他模块导入模块。 按惯例,所有 <a class="reference internal" href="../reference/simple_stmts.html#import"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">import</span></code></a> 语句都放在模块(或脚本)开头,但这不是必须的。 被导入的模块名存在导入方模块的全局符号表里。</p>
<p><a class="reference internal" href="../reference/simple_stmts.html#import"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">import</span></code></a> 语句有一个变体,可以直接把模块里的名称导入到另一个模块的符号表。例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">fibo</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<p>这段代码不会把模块名导入到局部符号表里(因此,本例没有定义 <code class="docutils literal notranslate"><span class="pre">fibo</span></code>)。</p>
<p>还有一种变体可以导入模块内定义的所有名称:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">fibo</span> <span class="kn">import</span> <span class="o">*</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<p>这种方式会导入所有不以下划线(<code class="docutils literal notranslate"><span class="pre">_</span></code>)开头的名称。大多数情况下,不要用这个功能,这种方式向解释器导入了一批未知的名称,可能会覆盖已经定义的名称。</p>
<p>注意,一般情况下,不建议从模块或包内导入 <code class="docutils literal notranslate"><span class="pre">*</span></code>,因为,这项操作经常让代码变得难以理解。不过,为了在交互式编译器中少打几个字,这么用也没问题。</p>
<p>模块名后使用 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">as</span></code> 时,直接把 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">as</span></code> 后的名称与导入模块绑定。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span> <span class="k">as</span> <span class="nn">fib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span><span class="o">.</span><span class="n">fib</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">fibo</span></code> 一样,这种方式也可以有效地导入模块,唯一的区别是,导入的名称是 <code class="docutils literal notranslate"><span class="pre">fib</span></code></p>
<p><a class="reference internal" href="../reference/simple_stmts.html#from"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">from</span></code></a> 中也可以使用这种方式,效果类似:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">fibo</span> <span class="kn">import</span> <span class="n">fib</span> <span class="k">as</span> <span class="n">fibonacci</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fibonacci</span><span class="p">(</span><span class="mi">500</span><span class="p">)</span>
<span class="go">0 1 1 2 3 5 8 13 21 34 55 89 144 233 377</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>为了保证运行效率,每次解释器会话只导入一次模块。如果更改了模块内容,必须重启解释器;仅交互测试一个模块时,也可以使用 <a class="reference internal" href="../library/importlib.html#importlib.reload" title="importlib.reload"><code class="xref py py-func docutils literal notranslate"><span class="pre">importlib.reload()</span></code></a>,例如 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">importlib;</span> <span class="pre">importlib.reload(modulename)</span></code></p>
</div>
<section id="executing-modules-as-scripts">
<span id="tut-modulesasscripts"></span><h3><span class="section-number">6.1.1. </span>以脚本方式执行模块<a class="headerlink" href="#executing-modules-as-scripts" title="永久链接至标题"></a></h3>
<p>可以用以下方式运行 Python 模块:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="n">fibo</span><span class="o">.</span><span class="n">py</span> <span class="o">&lt;</span><span class="n">arguments</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>这项操作将执行模块里的代码,和导入模块一样,但会把 <code class="docutils literal notranslate"><span class="pre">__name__</span></code> 赋值为 <code class="docutils literal notranslate"><span class="pre">&quot;__main__&quot;</span></code>。 也就是把下列代码添加到模块末尾:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">fib</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
</pre></div>
</div>
<p>这个文件既能被用作脚本又能被用作一个可供导入的模块因为解析命令行参数的那两行代码只有在模块作为“main”文件执行时才会运行</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>fibo.py<span class="w"> </span><span class="m">50</span>
<span class="go">0 1 1 2 3 5 8 13 21 34</span>
</pre></div>
</div>
<p>当这个模块被导入到其它模块时,那两行代码不运行:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
<span class="gp">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>这常用于为模块提供一个便捷的用户接口,或用于测试(把模块作为执行测试套件的脚本运行)。</p>
</section>
<section id="the-module-search-path">
<span id="tut-searchpath"></span><h3><span class="section-number">6.1.2. </span>模块搜索路径<a class="headerlink" href="#the-module-search-path" title="永久链接至标题"></a></h3>
<p id="index-0">当一个名为 <code class="xref py py-mod docutils literal notranslate"><span class="pre">spam</span></code> 的模块被导入的时候,解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 <a class="reference internal" href="../library/sys.html#sys.path" title="sys.path"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.path</span></code></a> 变量给出的目录列表里寻找名为 <code class="file docutils literal notranslate"><span class="pre">spam.py</span></code> 的文件。<a class="reference internal" href="../library/sys.html#sys.path" title="sys.path"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.path</span></code></a> 初始有这些目录地址:</p>
<ul class="simple">
<li><p>被命令行直接运行的脚本所在的目录(或未指定文件时的当前目录)。</p></li>
<li><p><span class="target" id="index-14"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONPATH"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONPATH</span></code></a> (目录列表,与 shell 变量 <span class="target" id="index-15"></span><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PATH</span></code> 的语法一样)。</p></li>
<li><p>取决于安装的默认设置</p></li>
</ul>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>在支持符号链接的文件系统中,“被命令行直接运行的脚本所在的目录”是符号链接最终指向的目录。换句话说,符号链接所在的目录并 <strong>没有</strong> 被添加至模块搜索路径。</p>
</div>
<p>初始化后Python 程序可以更改 <a class="reference internal" href="../library/sys.html#sys.path" title="sys.path"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.path</span></code></a>。脚本所在的目录先于标准库所在的路径被搜索。这意味着,脚本所在的目录如果有和标准库同名的文件,那么加载的是该目录里的,而不是标准库的。这一般是一个错误,除非这样的替换是你有意为之。详见 <a class="reference internal" href="#tut-standardmodules"><span class="std std-ref">标准模块</span></a></p>
</section>
<section id="compiled-python-files">
<h3><span class="section-number">6.1.3. </span>“已编译的” Python 文件<a class="headerlink" href="#compiled-python-files" title="永久链接至标题"></a></h3>
<p>为了快速加载模块Python 把模块的编译版本缓存在 <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> 目录中,文件名为 <code class="file docutils literal notranslate"><span class="pre">module.</span><em><span class="pre">version</span></em><span class="pre">.pyc</span></code>version 对编译文件格式进行编码,一般是 Python 的版本号。例如CPython 的 3.3 发行版中spam.py 的编译版本缓存为 <code class="docutils literal notranslate"><span class="pre">__pycache__/spam.cpython-33.pyc</span></code>。这种命名惯例让不同 Python 版本编译的模块可以共存。</p>
<p>Python 对比编译版与源码的修改日期,查看编译版是否已过期,是否要重新编译。此进程完全是自动的。此外,编译模块与平台无关,因此,可在不同架构的系统之间共享相同的库。</p>
<p>Python 在两种情况下不检查缓存。一,从命令行直接载入的模块,每次都会重新编译,且不储存编译结果;二,没有源模块,就不会检查缓存。为了让一个库能以隐藏源代码的形式分发(通过将所有源代码变为编译后的版本),编译后的模块必须放在源目录而非缓存目录中,并且源目录绝不能包含同名的未编译的源模块。</p>
<p>给专业人士的一些小建议:</p>
<ul class="simple">
<li><p>在 Python 命令中使用 <a class="reference internal" href="../using/cmdline.html#cmdoption-o"><code class="xref std std-option docutils literal notranslate"><span class="pre">-O</span></code></a><a class="reference internal" href="../using/cmdline.html#cmdoption-oo"><code class="xref std std-option docutils literal notranslate"><span class="pre">-OO</span></code></a> 开关,可以减小编译模块的大小。<code class="docutils literal notranslate"><span class="pre">-O</span></code> 去除断言语句,<code class="docutils literal notranslate"><span class="pre">-OO</span></code> 去除断言语句和 __doc__ 字符串。有些程序可能依赖于这些内容,因此,没有十足的把握,不要使用这两个选项。“优化过的”模块带有 <code class="docutils literal notranslate"><span class="pre">opt-</span></code> 标签,并且文件通常会一小些。将来的发行版或许会改进优化的效果。</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件读取的程序不比从 <code class="docutils literal notranslate"><span class="pre">.py</span></code> 读取的执行速度快,<code class="docutils literal notranslate"><span class="pre">.pyc</span></code> 文件只是加载速度更快。</p></li>
<li><p><a class="reference internal" href="../library/compileall.html#module-compileall" title="compileall: Tools for byte-compiling all Python source files in a directory tree."><code class="xref py py-mod docutils literal notranslate"><span class="pre">compileall</span></code></a> 模块可以为一个目录下的所有模块创建 .pyc 文件。</p></li>
<li><p>本过程的细节及决策流程图,详见 <span class="target" id="index-16"></span><a class="pep reference external" href="https://www.python.org/dev/peps/pep-3147"><strong>PEP 3147</strong></a></p></li>
</ul>
</section>
</section>
<section id="standard-modules">
<span id="tut-standardmodules"></span><h2><span class="section-number">6.2. </span>标准模块<a class="headerlink" href="#standard-modules" title="永久链接至标题"></a></h2>
<p id="index-4">Python 自带一个标准模块的库,它在 Python 库参考(此处以下称为&quot;库参考&quot; )里另外描述。 一些模块是内嵌到编译器里面的, 它们给一些虽并非语言核心但却内嵌的操作提供接口,要么是为了效率,要么是给操作系统基础操作例如系统调入提供接口。 这些模块集是一个配置选项, 并且还依赖于底层的操作系统。 例如,<a class="reference internal" href="../library/winreg.html#module-winreg" title="winreg: Routines and objects for manipulating the Windows registry. (Windows)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">winreg</span></code></a> 模块只在 Windows 系统上提供。一个特别值得注意的模块 <a class="reference internal" href="../library/sys.html#module-sys" title="sys: Access system-specific parameters and functions."><code class="xref py py-mod docutils literal notranslate"><span class="pre">sys</span></code></a>,它被内嵌到每一个 Python 编译器中。<code class="docutils literal notranslate"><span class="pre">sys.ps1</span></code><code class="docutils literal notranslate"><span class="pre">sys.ps2</span></code> 变量定义了一些字符,它们可以用作主提示符和辅助提示符:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps1</span>
<span class="go">&#39;&gt;&gt;&gt; &#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps2</span>
<span class="go">&#39;... &#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">ps1</span> <span class="o">=</span> <span class="s1">&#39;C&gt; &#39;</span>
<span class="go">C&gt; print(&#39;Yuck!&#39;)</span>
<span class="go">Yuck!</span>
<span class="go">C&gt;</span>
</pre></div>
</div>
<p>只有解释器用于交互模式时,才定义这两个变量。</p>
<p>变量 <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> 是字符串列表,用于确定解释器的模块搜索路径。该变量以环境变量 <span class="target" id="index-17"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONPATH"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONPATH</span></code></a> 提取的默认路径进行初始化,如未设置 <span class="target" id="index-18"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONPATH"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONPATH</span></code></a>,则使用内置的默认路径。可以用标准列表操作修改该变量:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;/ufs/guido/lib/python&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="the-dir-function">
<span id="tut-dir"></span><h2><span class="section-number">6.3. </span><a class="reference internal" href="../library/functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 函数<a class="headerlink" href="#the-dir-function" title="永久链接至标题"></a></h2>
<p>内置函数 <a class="reference internal" href="../library/functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 用于查找模块定义的名称。返回结果是经过排序的字符串列表:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span><span class="o">,</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">fibo</span><span class="p">)</span>
<span class="go">[&#39;__name__&#39;, &#39;fib&#39;, &#39;fib2&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">sys</span><span class="p">)</span>
<span class="go">[&#39;__displayhook__&#39;, &#39;__doc__&#39;, &#39;__excepthook__&#39;, &#39;__loader__&#39;, &#39;__name__&#39;,</span>
<span class="go"> &#39;__package__&#39;, &#39;__stderr__&#39;, &#39;__stdin__&#39;, &#39;__stdout__&#39;,</span>
<span class="go"> &#39;_clear_type_cache&#39;, &#39;_current_frames&#39;, &#39;_debugmallocstats&#39;, &#39;_getframe&#39;,</span>
<span class="go"> &#39;_home&#39;, &#39;_mercurial&#39;, &#39;_xoptions&#39;, &#39;abiflags&#39;, &#39;api_version&#39;, &#39;argv&#39;,</span>
<span class="go"> &#39;base_exec_prefix&#39;, &#39;base_prefix&#39;, &#39;builtin_module_names&#39;, &#39;byteorder&#39;,</span>
<span class="go"> &#39;call_tracing&#39;, &#39;callstats&#39;, &#39;copyright&#39;, &#39;displayhook&#39;,</span>
<span class="go"> &#39;dont_write_bytecode&#39;, &#39;exc_info&#39;, &#39;excepthook&#39;, &#39;exec_prefix&#39;,</span>
<span class="go"> &#39;executable&#39;, &#39;exit&#39;, &#39;flags&#39;, &#39;float_info&#39;, &#39;float_repr_style&#39;,</span>
<span class="go"> &#39;getcheckinterval&#39;, &#39;getdefaultencoding&#39;, &#39;getdlopenflags&#39;,</span>
<span class="go"> &#39;getfilesystemencoding&#39;, &#39;getobjects&#39;, &#39;getprofile&#39;, &#39;getrecursionlimit&#39;,</span>
<span class="go"> &#39;getrefcount&#39;, &#39;getsizeof&#39;, &#39;getswitchinterval&#39;, &#39;gettotalrefcount&#39;,</span>
<span class="go"> &#39;gettrace&#39;, &#39;hash_info&#39;, &#39;hexversion&#39;, &#39;implementation&#39;, &#39;int_info&#39;,</span>
<span class="go"> &#39;intern&#39;, &#39;maxsize&#39;, &#39;maxunicode&#39;, &#39;meta_path&#39;, &#39;modules&#39;, &#39;path&#39;,</span>
<span class="go"> &#39;path_hooks&#39;, &#39;path_importer_cache&#39;, &#39;platform&#39;, &#39;prefix&#39;, &#39;ps1&#39;,</span>
<span class="go"> &#39;setcheckinterval&#39;, &#39;setdlopenflags&#39;, &#39;setprofile&#39;, &#39;setrecursionlimit&#39;,</span>
<span class="go"> &#39;setswitchinterval&#39;, &#39;settrace&#39;, &#39;stderr&#39;, &#39;stdin&#39;, &#39;stdout&#39;,</span>
<span class="go"> &#39;thread_info&#39;, &#39;version&#39;, &#39;version_info&#39;, &#39;warnoptions&#39;]</span>
</pre></div>
</div>
<p>没有参数时,<a class="reference internal" href="../library/functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 列出当前已定义的名称:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">fibo</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">fib</span> <span class="o">=</span> <span class="n">fibo</span><span class="o">.</span><span class="n">fib</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">()</span>
<span class="go">[&#39;__builtins__&#39;, &#39;__name__&#39;, &#39;a&#39;, &#39;fib&#39;, &#39;fibo&#39;, &#39;sys&#39;]</span>
</pre></div>
</div>
<p>注意它列出所有类型的名称:变量,模块,函数,……。</p>
<p id="index-7"><a class="reference internal" href="../library/functions.html#dir" title="dir"><code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code></a> 不会列出内置函数和变量的名称。这些内容的定义在标准模块 <a class="reference internal" href="../library/builtins.html#module-builtins" title="builtins: The module that provides the built-in namespace."><code class="xref py py-mod docutils literal notranslate"><span class="pre">builtins</span></code></a> 中:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">builtins</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">dir</span><span class="p">(</span><span class="n">builtins</span><span class="p">)</span>
<span class="go">[&#39;ArithmeticError&#39;, &#39;AssertionError&#39;, &#39;AttributeError&#39;, &#39;BaseException&#39;,</span>
<span class="go"> &#39;BlockingIOError&#39;, &#39;BrokenPipeError&#39;, &#39;BufferError&#39;, &#39;BytesWarning&#39;,</span>
<span class="go"> &#39;ChildProcessError&#39;, &#39;ConnectionAbortedError&#39;, &#39;ConnectionError&#39;,</span>
<span class="go"> &#39;ConnectionRefusedError&#39;, &#39;ConnectionResetError&#39;, &#39;DeprecationWarning&#39;,</span>
<span class="go"> &#39;EOFError&#39;, &#39;Ellipsis&#39;, &#39;EnvironmentError&#39;, &#39;Exception&#39;, &#39;False&#39;,</span>
<span class="go"> &#39;FileExistsError&#39;, &#39;FileNotFoundError&#39;, &#39;FloatingPointError&#39;,</span>
<span class="go"> &#39;FutureWarning&#39;, &#39;GeneratorExit&#39;, &#39;IOError&#39;, &#39;ImportError&#39;,</span>
<span class="go"> &#39;ImportWarning&#39;, &#39;IndentationError&#39;, &#39;IndexError&#39;, &#39;InterruptedError&#39;,</span>
<span class="go"> &#39;IsADirectoryError&#39;, &#39;KeyError&#39;, &#39;KeyboardInterrupt&#39;, &#39;LookupError&#39;,</span>
<span class="go"> &#39;MemoryError&#39;, &#39;NameError&#39;, &#39;None&#39;, &#39;NotADirectoryError&#39;, &#39;NotImplemented&#39;,</span>
<span class="go"> &#39;NotImplementedError&#39;, &#39;OSError&#39;, &#39;OverflowError&#39;,</span>
<span class="go"> &#39;PendingDeprecationWarning&#39;, &#39;PermissionError&#39;, &#39;ProcessLookupError&#39;,</span>
<span class="go"> &#39;ReferenceError&#39;, &#39;ResourceWarning&#39;, &#39;RuntimeError&#39;, &#39;RuntimeWarning&#39;,</span>
<span class="go"> &#39;StopIteration&#39;, &#39;SyntaxError&#39;, &#39;SyntaxWarning&#39;, &#39;SystemError&#39;,</span>
<span class="go"> &#39;SystemExit&#39;, &#39;TabError&#39;, &#39;TimeoutError&#39;, &#39;True&#39;, &#39;TypeError&#39;,</span>
<span class="go"> &#39;UnboundLocalError&#39;, &#39;UnicodeDecodeError&#39;, &#39;UnicodeEncodeError&#39;,</span>
<span class="go"> &#39;UnicodeError&#39;, &#39;UnicodeTranslateError&#39;, &#39;UnicodeWarning&#39;, &#39;UserWarning&#39;,</span>
<span class="go"> &#39;ValueError&#39;, &#39;Warning&#39;, &#39;ZeroDivisionError&#39;, &#39;_&#39;, &#39;__build_class__&#39;,</span>
<span class="go"> &#39;__debug__&#39;, &#39;__doc__&#39;, &#39;__import__&#39;, &#39;__name__&#39;, &#39;__package__&#39;, &#39;abs&#39;,</span>
<span class="go"> &#39;all&#39;, &#39;any&#39;, &#39;ascii&#39;, &#39;bin&#39;, &#39;bool&#39;, &#39;bytearray&#39;, &#39;bytes&#39;, &#39;callable&#39;,</span>
<span class="go"> &#39;chr&#39;, &#39;classmethod&#39;, &#39;compile&#39;, &#39;complex&#39;, &#39;copyright&#39;, &#39;credits&#39;,</span>
<span class="go"> &#39;delattr&#39;, &#39;dict&#39;, &#39;dir&#39;, &#39;divmod&#39;, &#39;enumerate&#39;, &#39;eval&#39;, &#39;exec&#39;, &#39;exit&#39;,</span>
<span class="go"> &#39;filter&#39;, &#39;float&#39;, &#39;format&#39;, &#39;frozenset&#39;, &#39;getattr&#39;, &#39;globals&#39;, &#39;hasattr&#39;,</span>
<span class="go"> &#39;hash&#39;, &#39;help&#39;, &#39;hex&#39;, &#39;id&#39;, &#39;input&#39;, &#39;int&#39;, &#39;isinstance&#39;, &#39;issubclass&#39;,</span>
<span class="go"> &#39;iter&#39;, &#39;len&#39;, &#39;license&#39;, &#39;list&#39;, &#39;locals&#39;, &#39;map&#39;, &#39;max&#39;, &#39;memoryview&#39;,</span>
<span class="go"> &#39;min&#39;, &#39;next&#39;, &#39;object&#39;, &#39;oct&#39;, &#39;open&#39;, &#39;ord&#39;, &#39;pow&#39;, &#39;print&#39;, &#39;property&#39;,</span>
<span class="go"> &#39;quit&#39;, &#39;range&#39;, &#39;repr&#39;, &#39;reversed&#39;, &#39;round&#39;, &#39;set&#39;, &#39;setattr&#39;, &#39;slice&#39;,</span>
<span class="go"> &#39;sorted&#39;, &#39;staticmethod&#39;, &#39;str&#39;, &#39;sum&#39;, &#39;super&#39;, &#39;tuple&#39;, &#39;type&#39;, &#39;vars&#39;,</span>
<span class="go"> &#39;zip&#39;]</span>
</pre></div>
</div>
</section>
<section id="packages">
<span id="tut-packages"></span><h2><span class="section-number">6.4. </span><a class="headerlink" href="#packages" title="永久链接至标题"></a></h2>
<p>包是一种用“点式模块名”构造 Python 模块命名空间的方法。例如,模块名 <code class="xref py py-mod docutils literal notranslate"><span class="pre">A.B</span></code> 表示包 <code class="docutils literal notranslate"><span class="pre">A</span></code> 中名为 <code class="docutils literal notranslate"><span class="pre">B</span></code> 的子模块。正如模块可以区分不同模块之间的全局变量名称一样,点式模块名可以区分 NumPy 或 Pillow 等不同多模块包之间的模块名称。</p>
<p>假设要为统一处理声音文件与声音数据设计一个模块集(“包”)。声音文件的格式很多(通常以扩展名来识别,例如:<code class="file docutils literal notranslate"><span class="pre">.wav</span></code><code class="file docutils literal notranslate"><span class="pre">.aiff</span></code><code class="file docutils literal notranslate"><span class="pre">.au</span></code>),因此,为了不同文件格式之间的转换,需要创建和维护一个不断增长的模块集合。为了实现对声音数据的不同处理(例如,混声、添加回声、均衡器功能、创造人工立体声效果),还要编写无穷无尽的模块流。下面这个分级文件树展示了这个包的架构:</p>
<div class="highlight-text notranslate"><div class="highlight"><pre><span></span>sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
</pre></div>
</div>
<p>导入包时Python 搜索 <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> 里的目录,查找包的子目录。</p>
<p>Python 只把含 <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 文件的目录当成包。这样可以防止以 <code class="docutils literal notranslate"><span class="pre">string</span></code> 等通用名称命名的目录,无意中屏蔽出现在后方模块搜索路径中的有效模块。 最简情况下,<code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 只是一个空文件,但该文件也可以执行包的初始化代码,或设置 <code class="docutils literal notranslate"><span class="pre">__all__</span></code> 变量,详见下文。</p>
<p>还可以从包中导入单个模块,例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sound.effects.echo</span>
</pre></div>
</div>
<p>这段代码加载子模块 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.effects.echo</span></code> ,但引用时必须使用子模块的全名:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">sound</span><span class="o">.</span><span class="n">effects</span><span class="o">.</span><span class="n">echo</span><span class="o">.</span><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>另一种导入子模块的方法是 </p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">sound.effects</span> <span class="kn">import</span> <span class="n">echo</span>
</pre></div>
</div>
<p>这段代码还可以加载子模块 <code class="xref py py-mod docutils literal notranslate"><span class="pre">echo</span></code> ,不加包前缀也可以使用。因此,可以按如下方式使用:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">echo</span><span class="o">.</span><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>Import 语句的另一种变体是直接导入所需的函数或变量:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">sound.effects.echo</span> <span class="kn">import</span> <span class="n">echofilter</span>
</pre></div>
</div>
<p>同样,这样也会加载子模块 <code class="xref py py-mod docutils literal notranslate"><span class="pre">echo</span></code>,但可以直接使用函数 <code class="xref py py-func docutils literal notranslate"><span class="pre">echofilter()</span></code></p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">echofilter</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">output</span><span class="p">,</span> <span class="n">delay</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">atten</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>
</pre></div>
</div>
<p>注意,使用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">package</span> <span class="pre">import</span> <span class="pre">item</span></code>item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。<code class="docutils literal notranslate"><span class="pre">import</span></code> 语句首先测试包中是否定义了 item如果未在包中定义则假定 item 是模块,并尝试加载。如果找不到 item则触发 <a class="reference internal" href="../library/exceptions.html#ImportError" title="ImportError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ImportError</span></code></a> 异常。</p>
<p>相反,使用 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">item.subitem.subsubitem</span></code> 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。</p>
<section id="importing-from-a-package">
<span id="tut-pkg-import-star"></span><h3><span class="section-number">6.4.1. </span>从包中导入 *<a class="headerlink" href="#importing-from-a-package" title="永久链接至标题"></a></h3>
<p id="index-8">使用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">sound.effects</span> <span class="pre">import</span> <span class="pre">*</span></code> 时会发生什么?你可能希望它会查找并导入包的所有子模块,但事实并非如此。因为这将花费很长的时间,并且可能会产生你不想要的副作用,如果这种副作用被你设计为只有在导入某个特定的子模块时才应该发生。</p>
<p>唯一的解决办法是提供包的显式索引。<a class="reference internal" href="../reference/simple_stmts.html#import"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">import</span></code></a> 语句使用如下惯例:如果包的 <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 代码定义了列表 <code class="docutils literal notranslate"><span class="pre">__all__</span></code>,运行 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">package</span> <span class="pre">import</span> <span class="pre">*</span></code> 时,它就是被导入的模块名列表。发布包的新版本时,包的作者应更新此列表。如果包的作者认为没有必要在包中执行导入 * 操作,也可以不提供此列表。例如,<code class="file docutils literal notranslate"><span class="pre">sound/effects/__init__.py</span></code> 文件可以包含以下代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;echo&quot;</span><span class="p">,</span> <span class="s2">&quot;surround&quot;</span><span class="p">,</span> <span class="s2">&quot;reverse&quot;</span><span class="p">]</span>
</pre></div>
</div>
<p>这意味着 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">sound.effects</span> <span class="pre">import</span> <span class="pre">*</span></code> 将导入 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound</span></code> 包的三个命名子模块。</p>
<p>如果没有定义 <code class="docutils literal notranslate"><span class="pre">__all__</span></code><code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">sound.effects</span> <span class="pre">import</span> <span class="pre">*</span></code> 语句 <em>不会</em> 把包 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.effects</span></code> 中所有子模块都导入到当前命名空间;该语句只确保导入包 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.effects</span></code> (可能还会运行 <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 中的初始化代码),然后,再导入包中定义的名称。这些名称包括 <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 中定义的任何名称(以及显式加载的子模块),还包括之前 <a class="reference internal" href="../reference/simple_stmts.html#import"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">import</span></code></a> 语句显式加载的包里的子模块。请看以下代码:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sound.effects.echo</span>
<span class="kn">import</span> <span class="nn">sound.effects.surround</span>
<span class="kn">from</span> <span class="nn">sound.effects</span> <span class="kn">import</span> <span class="o">*</span>
</pre></div>
</div>
<p>本例中,执行 <code class="docutils literal notranslate"><span class="pre">from...import</span></code> 语句时,将把 <code class="xref py py-mod docutils literal notranslate"><span class="pre">echo</span></code><code class="xref py py-mod docutils literal notranslate"><span class="pre">surround</span></code> 模块导入至当前命名空间,因为,它们是在 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.effects</span></code> 包里定义的。(该导入操作在定义了 <code class="docutils literal notranslate"><span class="pre">__all__</span></code> 时也有效。)</p>
<p>虽然,可以把模块设计为用 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">*</span></code> 时只导出遵循指定模式的名称,但仍不提倡在生产代码中使用这种做法。</p>
<p>记住,使用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">package</span> <span class="pre">import</span> <span class="pre">specific_submodule</span></code> 没有任何问题! 实际上,除了导入模块使用不同包的同名子模块之外,这种方式是推荐用法。</p>
</section>
<section id="intra-package-references">
<h3><span class="section-number">6.4.2. </span>相对导入<a class="headerlink" href="#intra-package-references" title="永久链接至标题"></a></h3>
<p>包中内有多个子包时(与示例中的 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound</span></code> 包一样),可以使用绝对导入来引用兄弟包中的子模块。例如,要在模块 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.filters.vocoder</span></code> 中使用 <code class="xref py py-mod docutils literal notranslate"><span class="pre">sound.effects</span></code> 包的 <code class="xref py py-mod docutils literal notranslate"><span class="pre">echo</span></code> 模块时,可以用 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">sound.effects</span> <span class="pre">import</span> <span class="pre">echo</span></code> 导入。</p>
<p>还可以用 import 语句的 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">module</span> <span class="pre">import</span> <span class="pre">name</span></code> 形式执行相对导入。下面的导入语句使用前导句点表示相对导入中的当前包和父包。例如,相对于 <code class="xref py py-mod docutils literal notranslate"><span class="pre">surround</span></code> 模块,可以使用:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">.</span> <span class="kn">import</span> <span class="n">echo</span>
<span class="kn">from</span> <span class="nn">..</span> <span class="kn">import</span> <span class="n">formats</span>
<span class="kn">from</span> <span class="nn">..filters</span> <span class="kn">import</span> <span class="n">equalizer</span>
</pre></div>
</div>
<p>注意,相对导入基于当前模块名。因为主模块名永远是 <code class="docutils literal notranslate"><span class="pre">&quot;__main__&quot;</span></code> ,所以如果计划将一个模块用作 Python 应用程序的主模块,那么该模块内的导入语句必须始终使用绝对导入。</p>
</section>
<section id="packages-in-multiple-directories">
<h3><span class="section-number">6.4.3. </span>多目录中的包<a class="headerlink" href="#packages-in-multiple-directories" title="永久链接至标题"></a></h3>
<p>包还支持一个特殊属性 <a class="reference internal" href="../reference/import.html#__path__" title="__path__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__path__</span></code></a> 。在包的 <code class="file docutils literal notranslate"><span class="pre">__init__.py</span></code> 中的代码被执行前,该属性被初始化为一个只含一项的列表,该项是一个字符串,是 __init__.py 所在目录的名称。可以修改此变量;这样做会改变在此包中搜索模块和子包的方式。</p>
<p>这个功能虽然不常用,但可用于扩展包中的模块集。</p>
<p class="rubric">备注</p>
<dl class="footnote brackets">
<dt class="label" id="id2"><span class="brackets"><a class="fn-backref" href="#id1">1</a></span></dt>
<dd><p>实际上,函数定义也是“可执行”的“语句”;执行模块级函数定义时,函数名将被导入到模块的全局符号表。</p>
</dd>
</dl>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">6. 模块</a><ul>
<li><a class="reference internal" href="#more-on-modules">6.1. 模块详解</a><ul>
<li><a class="reference internal" href="#executing-modules-as-scripts">6.1.1. 以脚本方式执行模块</a></li>
<li><a class="reference internal" href="#the-module-search-path">6.1.2. 模块搜索路径</a></li>
<li><a class="reference internal" href="#compiled-python-files">6.1.3. “已编译的” Python 文件</a></li>
</ul>
</li>
<li><a class="reference internal" href="#standard-modules">6.2. 标准模块</a></li>
<li><a class="reference internal" href="#the-dir-function">6.3. <code class="xref py py-func docutils literal notranslate"><span class="pre">dir()</span></code> 函数</a></li>
<li><a class="reference internal" href="#packages">6.4. 包</a><ul>
<li><a class="reference internal" href="#importing-from-a-package">6.4.1. 从包中导入 *</a></li>
<li><a class="reference internal" href="#intra-package-references">6.4.2. 相对导入</a></li>
<li><a class="reference internal" href="#packages-in-multiple-directories">6.4.3. 多目录中的包</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="datastructures.html"
title="上一章"><span class="section-number">5. </span>数据结构</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="inputoutput.html"
title="下一章"><span class="section-number">7. </span>输入与输出</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/tutorial/modules.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
>索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="inputoutput.html" title="7. 输入与输出"
>下一页</a> |</li>
<li class="right" >
<a href="datastructures.html" title="5. 数据结构"
>上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python 教程</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
最后更新于 12月 09, 2024.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
</div>
</body>
</html>