python学习笔记——模块

单文件程序执行解析(模块与脚本运行)

Python 中单个.py 文件的执行机制,核心概念是「模块(module)」和「脚本运行」的区别,我帮你拆解所有关键点:

一、核心概念:Python 模块(Module)

每个 .py 文件都被视为一个独立的 Python 模块。
模块包含自己的变量、函数、类和可执行代码,有独立的命名空间,不会和其他模块冲突。
可以用 import 模块名 的方式,在其他文件中导入并复用这个模块的代码。

二、模块相关内置工具与变量

1. dir() 函数

作用:查看模块(或对象)中定义的所有变量、函数、类等绑定关系。
示例:在 test.py 中调用 dir(),会列出该模块的所有属性(包括内置的 name、自定义变量等)。

2. name 变量

存储当前模块的名称,有两种关键场景:
当文件被直接作为脚本运行时,name 的值为 'main'。
当文件被作为模块导入时,name 的值为文件名(不带 .py,比如 'test')。

if __name__ == '__main__':
    # 只有直接运行脚本时,才会执行这里的代码
    print("这是直接运行脚本时才会执行的逻辑")

这样可以避免导入模块时自动执行脚本的主逻辑。

三、脚本运行时的命令行参数(sys.argv)

  1. 基本概念
    sys.argv 是 sys 模块中的一个列表,用于获取运行脚本时传入的控制台参数。
    列表的第一个元素 sys.argv[0] 永远是脚本的文件名,后面的元素才是用户传入的参数。
  2. 示例解析
    以 PPT 中的代码和命令为例:
# test.py 文件内容
import sys
print(sys.argv)
运行
python test.py abc xyz
输出结果:
plaintext
['test.py', 'abc', 'xyz']

sys.argv[0] = 'test.py'(脚本文件名)
sys.argv[1] = 'abc'(第一个用户参数)
sys.argv[2] = 'xyz'(第二个用户参数)

  1. 常见用法
    可以通过 sys.argv 实现简单的脚本命令行交互,比如:
import sys
if len(sys.argv) != 3:
    print("用法:python test.py <参数1> <参数2>")
else:
    param1 = sys.argv[1]
    param2 = sys.argv[2]
    print(f"你传入的参数:{param1}, {param2}")

四、关键总结

模块与脚本的本质:每个 .py 文件既是模块,也可以作为脚本运行,两者的区别体现在 name 变量上。
dir() 用于查看模块内容,name 区分运行场景,sys.argv 获取命令行参数,这三个是单文件程序执行的核心工具。
if name == 'main': 是 Python 脚本的标准写法,能同时支持「直接运行」和「被导入」两种场景。

多文件协作的核心机制 —— 模块导入

一、导入模块时到底发生了什么?

当你执行 import test_print 时,Python 会按顺序做这几件事:

  1. 执行模块的全部代码
  2. 定义所有函数(如 printID、work_print)
  3. 执行模块里的顶层代码(如 x = 3、printID(x) 等测试代码)
  4. 创建模块对象,记录绑定关系(所有变量、函数的绑定关系,都被记录在模块自己的 ** 符号表(命名空间)** 中
    模块的命名空间和当前文件的命名空间是相互隔离的,不会互相干扰)

二、PPT 示例代码的执行效果

以右侧的 test_print.py 为例:

def printID(x):
    print(x, ":", id(x))

def work_print(x):
    x += 5
    printID(x)

x = 3
printID(x)
work_print(x)
printID(x)

当这个模块被导入时,控制台会直接输出:

3 : <地址>
8 : <地址>
3 : <地址>

注意:work_print 里的 x += 5 只是修改了函数内的局部变量,不会影响模块顶层的 x,所以最后一行 printID(x) 依然打印 3。

三、两个核心问题的解答

问题 1:如何处理导入模块和当前模块的不同绑定关系?

  • 答案:模块和当前文件拥有独立的命名空间,绑定关系互相隔离。
    模块里的变量、函数都属于模块的命名空间,访问时必须加 模块名. 前缀,比如 test_print.x、test_print.printID。
    即使当前文件定义了同名变量 x,和模块里的 test_print.x 也是完全不同的变量,互不影响。

问题 2:如何处理导入模块和当前模块中的执行代码?

  • 答案:模块导入时,顶层执行代码会被直接执行;而通过 if name == 'main': 可以控制测试代码只在直接运行时执行。
    模块导入时,文件中所有不在函数 / 类里的顶层代码(如 x = 3、printID(x))都会被执行,这就是为什么导入模块时会看到打印输出。
    要避免导入时执行测试代码,可以把测试逻辑放进 if name == 'main': 块里:
def printID(x):
    print(x, ":", id(x))

def work_print(x):
    x += 5
    printID(x)

if __name__ == '__main__':
    x = 3
    printID(x)
    work_print(x)
    printID(x)

这样,模块被导入时,测试代码不会执行;只有直接运行 python test_print.py 时,才会执行测试代码。

四、和 C++ 的关键区别

C++ 每个可执行文件有唯一的 main 函数作为入口,头文件不执行代码,只声明。
Python 没有强制的 main 函数,任何 .py 文件都可以作为脚本运行,导入时会执行模块的全部顶层代码。
💡 补充:如果你想让模块被导入时不执行任何额外代码,只要把所有执行逻辑都放进 if name == 'main': 块里即可,这是 Python 模块化开发的标准做法。

posted @ 2026-05-11 20:18  RReally  阅读(21)  评论(0)    收藏  举报
//一下两个链接最好自己保存下来,再上传到自己的博客园的“文件”选项中