Python学习从0开始——006模块

本文详细介绍了Python中的模块概念,包括如何导入模块、脚本方式运行模块、模块搜索路径、标准模块库、dir()函数的作用以及包的导入、相对导入和多目录包的管理。重点讲解了如何使用`import`语句和包的结构设计。
摘要由CSDN通过智能技术生成

一、定义

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
#终端
>>> import 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 

二、模块详解

2.1引入

#其它引入方式:
#模块名后使用 as 时,直接把 as 后的名称与导入模块绑定
>>> import fibo as fib
#与 import fibo 一样,唯一的区别是导入的名称是 fib
>>> fib.__name__
'fibo'
#把 as 后的名称与导入函数绑定
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 

2.2脚本方式运行

python fibo.py <arguments>

这项操作将执行模块里的代码,和导入模块一样,但会把 name 赋值为 “main”。 也就是把下列代码添加到模块末尾:

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

这个文件既能被用作脚本,又能被用作一个可供导入的模块,因为解析命令行参数的那两行代码只有在模块作为“main”文件执行时才会运行,当这个模块被导入到其它模块时,那两行代码不运行。常用于为模块提供一个便捷的用户接口,或用于测试(把模块作为执行测试套件的脚本运行)。

#fibo.py
import argparse  
  
def fib(n):    
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result
  
def main(): 
	#对这个命令行工具的描述,通常会在用户请求帮助时显示 
    parser = argparse.ArgumentParser(description='Print Fibonacci series up to n.')  
    #使用 add_argument 方法添加一个命令行参数。
	#'n' 是这个参数的名字,用户在命令行中提供这个参数的值时不需要使用任何前缀(如 -- 或 -)。
	#type=int 指定参数是一个整数。如果用户提供了一个非整数值,argparse 会抛出一个错误。
    parser.add_argument('n', type=int, help='an integer for the upper limit of the Fibonacci series')  
    args = parser.parse_args()  
      
    fib_sequence = fib(args.n)  
    print(fib_sequence)  
  
if __name__ == "__main__":  
    main()

#终端
~/Python python fibo.py -h
usage: fibo.py [-h] n

Print Fibonacci series up to n.

positional arguments:
  n           an integer for the upper limit of the Fibonacci series

optional arguments:
  -h, --help  show this help message and exit
~/Python python fibo.py 1000
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]

在这里插入图片描述

2.3模块搜索路径

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

被命令行直接运行的脚本所在的目录(或未指定文件时的当前目录)。
PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
依赖于安装的默认值(按照惯例包括一个 site-packages 目录,由 site 模块处理)。

2.4编译版本缓存

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

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

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

三、标准模块

Python 自带一个标准模块的库, 一些模块是内嵌到编译器里面的, 它们给一些虽并非语言核心但却内嵌的操作提供接口,要么是为了效率,要么是给操作系统基础操作例如系统调入提供接口。 这些模块集是一个配置选项, 并且还依赖于底层的操作系统。 例如,winreg 模块只在 Windows 系统上提供。一个特别值得注意的模块 sys,它被内嵌到每一个 Python 编译器中。

四、dir() 函数

内置函数 dir() 用于查找模块定义的名称。返回结果是经过排序的字符串列表:
在这里插入图片描述
没有参数时,dir() 列出当前已定义的名称,注意它列出所有类型的名称:变量,模块,函数,……,但是不会列出内置函数和变量的名称。

五、包

5.1导入

包是通过使用“带点号模块名”来构造 Python 模块命名空间的一种方式。 例如,模块名 A.B 表示名为 A 的包中名为 B 的子模块。
包层级示例:

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
              ...

导入包时,Python 搜索 sys.path 里的目录,查找包的子目录。
需要有’_init_.py ‘文件才能让 Python 将包含该文件的目录当作包来处理(除非使用 namespace package,这是一个相对高级的特性)。 这可以防止重名的目录如 string 在无意中屏蔽后继出现在模块搜索路径中的有效模块。 在最简单的情况下,’_init_.py '可以只是一个空文件,但它也可以执行包的初始化代码或设置 '_all_ '变量。

#单个模块导入
import sound.effects.echo
#调用此模块的函数,必须全名引用
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

#方法二,调用不用加包前缀
from sound.effects import echo
echo.echofilter(input, output, delay=0.7, atten=4)

#方法三,此时函数直接可用
from sound.effects.echo import echofilter
echofilter(input, output, delay=0.7, atten=4)

使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。import 语句首先测试包中是否定义了 item;如果未在包中定义,则假定 item 是模块,并尝试加载。如果找不到 item,则触发 ImportError 异常。
相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。

5.2从包中导入 *

如果包的 ‘_init_.py ‘代码定义了列表’_all_’,运行 from package import * 时,它就是被导入的模块名列表。发布包的新版本时,包的作者应更新此列表。如果包的作者认为没有必要在包中执行导入 * 操作,也可以不提供此列表。

# sound/effects/__init__.py 
__all__ = ["echo", "surround", "reverse"]

但是以下这种形式,子模块会被本地定义的 reverse 函数遮挡

# sound/effects/__init__.py 
__all__ = [
    "echo",      
    "surround",  
    "reverse",   
]

def reverse(msg: str):  
    return msg[::-1] 

如果没有定义 ‘_all_’,from sound.effects import * 语句 不会把包 sound.effects 中的所有子模块都导入到当前命名空间;它只是确保包 sound.effects 已被导入(可能还会运行 '_init_.py '中的所有初始化代码),然后再导入包中定义的所有名称。 这包括由 '_init_.py '定义的所有名称(以及显式加载的子模块)。 它还包括先前 import 语句显式加载的包里的任何子模块。
所以,生产不推荐*。

5.3 相对导入

相对导入基于当前模块名。因为主模块名永远是 “_main_” ,所以如果计划将一个模块用作 Python 应用程序的主模块,那么该模块内的导入语句必须始终使用绝对导入。

from . import echo
from .. import formats
from ..filters import equalizer

5.4多目录中的包

包还支持一个特殊属性 ‘_path_’ 。在包的 ‘_init_.py’中的代码被执行前,该属性被初始化为一个只含一项的列表,该项是一个字符串,是’_init_.py’所在目录的名称。可以修改此变量;这样做会改变在此包中搜索模块和子包的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值