找回密码
 立即注册
搜索
到手67.99元!阿里云轻量2核2G云服务器
查看: 29|回复: 0

模块

[复制链接]

696

主题

0

回帖

11

积分

管理员

积分
11
发表于 2026-4-20 18:21:13 来自手机 | 显示全部楼层 |阅读模式
退出 Python 解释器后,再次进入时,之前在 Python 解释器中定义的函数和变量就丢失了。因此,编写较长程序时,最好用文本编辑器代替解释器,执行文件中的输入内容,这就是编写 脚本 。随着程序越来越长,为了方便维护,最好把脚本拆分成多个文件。编写脚本还有一个好处,不同程序调用同一个函数时,不用把函数定义复制到各个程序。

为实现这些需求,Python 把各种定义存入一个文件,在脚本或解释器的交互式实例中使用。这个文件就是 模块 ;模块中的定义可以 导入 到其他模块或 主 模块(在顶层和计算器模式下,执行脚本中可访问的变量集)。

模块是包含 Python 定义和语句的文件。其文件名是模块名加后缀名 .py 。在模块内部,通过全局变量 __name__ 可以获取模块名(即字符串)。例如,用文本编辑器在当前目录下创建 fibo.py 文件,输入以下内容:

# 斐波那契数列模块

def fib(n):
    """Write Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):
    """Return Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result
现在,进入 Python 解释器,用以下命令导入该模块:

import fibo
此操作不会直接把 fibo 中定义的函数名称添加到当前 namespace 中(请参阅 Python 作用域和命名空间 了解详情);它只是将模块名称 fibo 添加到那里。 使用该模块名称你可以访问其中的函数:

fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
fibo.__name__
'fibo'
如果经常使用某个函数,可以把它赋值给局部变量:

fib = fibo.fib
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行。[1] (文件作为脚本运行时,也会执行这些语句。)

每个模块都有它自己的私有符号表,该表被定义在该模块里的所有函数当作全局符号表使用。 因此,一个模块的作者可以在模块内放心使用全局变量,而不必担心它们会和模块使用者的全局变量发生意外冲突。 另一方面,如果您知道自己在做什么,您可以使用与引用模块函数相同的语法去访问一个模块的全局变量,即 modname.itemname。

模块可以导入其他模块。 根据惯例可以将所有 import 语句都放在模块(或者也可以说是脚本)的开头但这并非强制要求。 如果被放置于一个模块的最高层级,则被导入的模块名称会被添加到该模块的全局命名空间。

还有一种 import 语句的变化形式可以将来自某个模块的名称直接导入到导入方模块的命名空间中。 例如:

from fibo import fib, fib2
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
这条语句不会将所导入的模块的名称引入到局部命名空间中(因此在本示例中,fibo 将是未定义的名称)。

还有一种变体可以导入模块内定义的所有名称:

from fibo import *
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
这种方式会导入所有不以下划线(_)开头的名称。大多数情况下,不要用这个功能,这种方式向解释器导入了一批未知的名称,可能会覆盖已经定义的名称。

注意,一般情况下,不建议从模块或包内导入 *,因为,这项操作经常让代码变得难以理解。不过,为了在交互式会话中少打几个字,这么用也没问题。

模块名后使用 as 时,直接把 as 后的名称与导入模块绑定。

import fibo as fib
fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
与 import fibo 一样,这种方式也可以有效地导入模块,唯一的区别是,导入的名称是 fib。

from 中也可以使用这种方式,效果类似:

from fibo import fib as fibonacci
fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
备注 为了保证运行效率,每次解释器会话只导入一次模块。如果更改了模块内容,必须重启解释器;仅交互测试一个模块时,也可以使用 importlib.reload(),例如 import importlib; importlib.reload(modulename)。

1. 以脚本方式执行模块
可以用以下方式运行 Python 模块:

python fibo.py <arguments>
这项操作将执行模块里的代码,和导入模块一样,但会把 __name__ 赋值为 "__main__"。 也就是把下列代码添加到模块末尾:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))
这个文件既能被用作脚本,又能被用作一个可供导入的模块,因为解析命令行参数的那两行代码只有在模块作为“main”文件执行时才会运行:

python fibo.py 50
0 1 1 2 3 5 8 13 21 34
当这个模块被导入到其它模块时,那两行代码不运行:

import fibo

这常用于为模块提供一个便捷的用户接口,或用于测试(把模块作为执行测试套件的脚本运行)。

2. 模块搜索路径
当导入一个名为 spam 的模块时,解释器首先会搜索具有该名称的内置模块。 这些模块的名称在 sys.builtin_module_names 中列出。 如果未找到,它将在变量 sys.path 所给出的目录列表中搜索名为 spam.py 的文件。 sys.path 是从这些位置初始化的:

被命令行直接运行的脚本所在的目录(或未指定文件时的当前目录)。

PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。

依赖于安装的默认值(按照惯例包括一个 site-packages 目录,由 site 模块处理)。

更多细节请参阅 sys.path 模块搜索路径的初始化。

备注 在支持符号链接的文件系统中,“被命令行直接运行的脚本所在的目录”是符号链接最终指向的目录。换句话说,符号链接所在的目录并 没有 被添加至模块搜索路径。
初始化后,Python 程序可以更改 sys.path。脚本所在的目录先于标准库所在的路径被搜索。这意味着,脚本所在的目录如果有和标准库同名的文件,那么加载的是该目录里的,而不是标准库的。这一般是一个错误,除非这样的替换是你有意为之。详见 标准模块。

3. “已编译的” Python 文件
为了快速加载模块,Python 把模块的编译版本缓存在 __pycache__ 目录中,文件名为 module.version.pyc,version 对编译文件格式进行编码,一般是 Python 的版本号。例如,CPython 的 3.3 发行版中,spam.py 的编译版本缓存为 __pycache__/spam.cpython-33.pyc。这种命名惯例让不同 Python 版本编译的模块可以共存。

Python 对比编译版与源码的修改日期,查看编译版是否已过期,是否要重新编译。此进程完全是自动的。此外,编译模块与平台无关,因此,可在不同架构的系统之间共享相同的库。

Python 在两种情况下不检查缓存。一,从命令行直接载入的模块,每次都会重新编译,且不储存编译结果;二,没有源模块,就不会检查缓存。为了让一个库能以隐藏源代码的形式分发(通过将所有源代码变为编译后的版本),编译后的模块必须放在源目录而非缓存目录中,并且源目录绝不能包含同名的未编译的源模块。

给专业人士的一些小建议:

在 Python 命令中使用 -O 或 -OO 开关,可以减小编译模块的大小。-O 去除断言语句,-OO 去除断言语句和 __doc__ 字符串。有些程序可能依赖于这些内容,因此,没有十足的把握,不要使用这两个选项。“优化过的”模块带有 opt- 标签,并且文件通常会小一些。将来的发行版或许会改进优化的效果。

从 .pyc 文件读取的程序不比从 .py 读取的执行速度快,.pyc 文件只是加载速度更快。

compileall 模块可以为一个目录下的所有模块创建 .pyc 文件。

本过程的细节及决策流程图,详见 PEP 3147。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|skypiea

GMT+8, 2026-6-27 05:17 , Processed in 0.070886 second(s), 20 queries .

Powered by skypiea

快速回复 返回顶部 返回列表