Python中的模块

1. 概述

模块是一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py
在一个模块内部,模块名(作为一个字符串)可以通过全局变量 name 的值获得。
在一个模块中导入另一个模块使用关键字import,后跟模块的名字。

fibo.py

# Fibonacci numbers module


if __name__ == 'fibo':
    print('module name == ', __name__)


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()


# return Fibonacci series up to n
def fib2(n):
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

main.py

import fibo


fibo.fib(100)

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 

Process finished with exit code 0

模块可以包含可执行的语句以及函数定义。这些语句用于初始化模块。它们仅在模块 第一次 在 import 语句中被导入时才执行。
每个模块都有它自己的私有符号表。,该表用作模块中定义的所有函数的全局符号表。仅限于在该模块中可见。不必担心与导入它的其他模块的全局变量发生意外冲突。
模块可以导入其它模块。习惯上把所有 import 语句放在模块(或脚本)的开头(但是不要求必须这样做。)

2. 导入模块

2.1 导入整个模块的符号名称

语法1:
import <模块名>


被导入的模块名存放在调入模块的全局符号表中。导入的符号包括以下划线 _ 开始的名称。


main.py

import fibo


fibo.fib(100)
print('fibo module name = ', fibo.__name__)

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 
fibo module name =  fibo

Process finished with exit code 0

语法2:
from <模块名> import *


导入模块内定义的所有名称,但是不会导入以下划线 _ 开头的符号名称。


main.py

from fibo import *


fib(100)

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 

Process finished with exit code 0

2.2 导入一个模块中的部分符号名称

导入部分符号,各符号之间使用逗号分隔
*这种导入方式不会把被调模块名(如fibo)引入到局部变量表中(即main模块中)。

from fibo import fib, fib2


fib(500)

lst = fib2(100)
for i in lst:
    print(i, end=' ')

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 
0 1 1 2 3 5 8 13 21 34 55 89 
Process finished with exit code 0

2.3 使用as关键字给模块命名别名

如果模块名称之后带有 as,则跟在 as 之后的名称将直接绑定到所导入的模块。as之后的名称作为被导入模块的别名。

import fibo as fib


fib.fib(500)

lst = fib.fib2(100)
for i in lst:
    print(i, end=' ')

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 
0 1 1 2 3 5 8 13 21 34 55 89 
Process finished with exit code 0

2.4 使用as关键字给模块中的符号命名别名

在被导入符号的名字后跟as关键字,并且as后跟别名

from fibo import fib as fibonacci


fibonacci(500)

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 

Process finished with exit code 0

注解 出于效率的考虑,每个模块在每个解释器会话中只被导入一次。因此,如果你更改了你的模块,则必须重新启动解释器, 或者,如果它只是一个要交互式地测试的模块,请使用 importlib.reload(),例如 import importlib; importlib.reload(modulename)。

3. 以脚本的方式执行模块

查看脚本所在的路径:
在这里插入图片描述
在命令行同过python执行模块,模块里的代码会被执行,就像导入了模块一样,但是模块的__name__被赋值为__main__。
在模块的代码末尾加 if _ name _ == “_ main _”:,只有模块同过命令行调用执行时,这块代码才会执行,但是如果同过在另一个模块中导入,这个代码块是不会被执行的。
修改fibo.py:

# Fibonacci numbers module


if __name__ == 'fibo':
    print('module name == ', __name__)


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()


# return Fibonacci series up to n
def fib2(n):
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result


if __name__ == '__main__':
    print('in module fibo')
    fib(100)

在命令行,执行脚本(不传参)
在这里插入图片描述
修改fibo.py,处理命令行参数:

if __name__ == '__main__':
    import sys
    print('in module fibo')
    fib(int(sys.argv[1]))

在命令行,执行脚本(传参)
在这里插入图片描述

4. 模块的搜索路径

当一个名为 spam 的模块被导入的时候,解释器首先寻找具有该名称的内置模块。如果没有找到,然后解释器从 sys.path 变量给出的目录列表里寻找名为 spam.py 的文件。
sys.path 的初始目录有:
1. 模块文件所在的目录
2. PYTHONPATH环境变量中的目录列表
3. Python的安装目录


在模块初始化后,Python程序可以更改 sys.path。包含正在运行脚本的文件目录被放在搜索路径的开头处, 在标准库路径之前。这意味着将加载此目录里的脚本,而不是标准库中的同名模块。
sys.path 变量是一个字符串列表,用于确定解释器的模块搜索路径,该变量被初始化为从环境变量 PYTHONPATH 获取的默认路径,或者如果 PYTHONPATH 未设置,则从内置默认路径初始化。
也可以使用标准列表操作对其进行修改:
在这里插入图片描述

5. “编译过的”Python文件

为了加速模块载入,Python在 pycache 目录里缓存了每个模块的编译后版本,名称为 module.version.pyc,例如fibo.py模块:
在这里插入图片描述
其中名称中的版本字段对编译文件的格式进行编码; 它一般使用Python版本号。上面的38对应的是Python3.8。此命名约定允许来自不同发行版和不同版本的Python的已编译模块共存。


Python根据编译版本检查源的修改日期,以查看它是否已过期并需要重新编译。这是一个完全自动化的过程。此外,编译的模块与平台无关,因此可以在具有不同体系结构的系统之间共享相同的库。


Python在两种情况下不会检查缓存:
1. 对于从命令行直接载入的模块,它从来都是重新编译并且不存储编译结果
2. 如果没有源模块,它不会检查缓存。

6. 标准模块

Python附带了一个标准模块库,一些模块内置于解释器中。例如 sys模块,它被内嵌到每一个Python解释器中,变量 sys.ps1sys.ps2 定义用作主要和辅助提示的字符串,这两个变量只有在编译器是交互模式下才被定义。
在这里插入图片描述
更改辅助提示字符串:
在这里插入图片描述

7. 内置函数dir()

内置函数 dir() 用于查找模块中定义的符号名称。 它返回一个排序过的(升序)字符串列表
注意:它列出所有类型的名称:变量,模块,函数,等等。dir() 不会列出内置函数和变量的名称。如果你想要这些,它们的定义是在标准模块 builtins 中:

import fibo

print(type(dir(fibo)), ' : ' ,dir(fibo))

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
<class 'list'>  :  ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fib2']

Process finished with exit code 0

如果dir()不带参数,则默认查找当前模块的符号名称:

import fibo

testStr = 'this is main module'

print(type(dir(fibo)), ' : ', dir(fibo))

print(type(dir()), ' : ', dir())

输出:

E:\Python3\Exercise\venvs\Scripts\python.exe C:/Users/Administrator/PycharmProjects/pythonProject/main.py
module name ==  fibo
<class 'list'>  :  ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fib2']
<class 'list'>  :  ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fibo', 'testStr']

Process finished with exit code 0

8. 包

包是一种通过用 “带点号的模块名” 来构造 Python 模块命名空间的方法。
例如,模块名 A.B 表示 A 包中名为 B 的子模块。如下使用PyCharm创建一个名为A的包,它会在这个A包下自动创建一个名为 _ init _.py 的包初始化文件:
在这里插入图片描述
包其实就是一个目录:
在这里插入图片描述
必须要有 _ init _.py 文件才能让 Python 将包含 _ init _.py文件的目录当作包。
_ init _.py 刚被创建时它是一个空文件,但它也可以执行包的初始化代码或设置 _ all _ 变量
当导入这个包时,Python搜索 sys.path 里的目录,查找包的子目录。

创建A.B.C包,其中B是A的子包,C是B的子包,如下图的结构关系:
在这里插入图片描述

8.1 导入包中的模块

8.1.1 导入子包中的单个模块

例如导入A.B.C包中的CHello模块
CHello模块的代码:
在这里插入图片描述
C子包中_ init _py的 内容:
在这里插入图片描述
main.py中的代码
在这里插入图片描述
输出结果:

D:\Work\PRJS\pythonProject\pythonProject4\venv\Scripts\python.exe D:/Work/PRJS/pythonProject/pythonProject4/venv/main.py
import module of C packet
Hello, World! I'm in C subpacket

Process finished with exit code 0

在引用导入的子模块中的函数或者说是变量时,必须使用它的全名进行引用,如上面的A.B.C.CHello.Hello()

8.1.2 使用关键字from导入包中的模块

from A.B.C import CHello


CHello.Hello()

输出:

D:\Work\PRJS\pythonProject\pythonProject4\venv\Scripts\python.exe D:/Work/PRJS/pythonProject/pythonProject4/venv/main.py
import module of C packet
Hello, World! I'm in C subpacket

Process finished with exit code 0

使用关键字from导入子包中的模块,子包路径必须是完整的包路径,不能是诸如如下的形式:

from A.B import C.CHello


C.CHello.Hello()

8.2 导入包中的所有模块(from package import *)

设置包的显示索引列表,即在其他模块中导入包中的所有模块时,为了避免导入一个子包中的所有模块,可以设置允许导出模块,通过子包中的__init__.py模块中的_ all _属性列表来设置。
在这里插入图片描述
C包的__init__.py模块

__all__ = ["CHello", "CEcho"]
print('import module of C packet')

输出:

D:\Work\PRJS\pythonProject\pythonProject4\venv\Scripts\python.exe D:/Work/PRJS/pythonProject/pythonProject4/venv/main.py
import module of C packet
Hello, World! I'm in C subpacket
echo -----------! I'm in C subpacket

Process finished with exit code 0

没有在包的_ all _ 模块列表中的模块是导不出来的。

8.3 子包的相对导入

当包被构造成子包时,你可以使用绝对导入来引用兄弟包的子模块。还可以使用import语句的 from module import name 形式编写相对导入。这些导入使用前导点(.或…)来指示相对导入中涉及的当前包和父包。
在这里插入图片描述

from . import CEcho         # 相对当前模块所在包的导入
from .. import BHello       # 相对当前模块所在包的父包中的模块导入
from A import AHello        # 绝对包模块路径导入
def Hello():
    CEcho.Echo()
    BHello.Hello()
    print("Hello, World! I'm in C subpacket")

输出:

D:\Work\PRJS\pythonProject\pythonProject4\venv\Scripts\python.exe D:/Work/PRJS/pythonProject/pythonProject4/venv/main.py
import module of C packet
echo -----------! I'm in C subpacket
Hello, World! I'm in B subpacket
Hello, World! I'm in C subpacket

Process finished with exit code 0

[上一页][下一页]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值