Python的基础:模块(Modules)和包(Packages)详解

1. 模块(Modules)

  一个模块是一个包含了 Python 定义和语句的文件。模块可以包括变量、函数、类等,并且提供了一种将相关代码组织成可重用单元的方式。一个模块的定义通常包括以下几个方面:
  1)文件扩展名:块的文件通常使用.py作为扩展名,表示这是一个Python源代码文件。
  2)模块代码:文件中包含了模块的实际代码,即变量、函数、类等的定义,这些定义的代码可以被其他模块或脚本导入和使用。
  3)文档字符串(docstring):通常,一个模块会包含一个文档字符串,用于提供关于模块功能的描述。这对于代码的文档和可读性非常重要。

1.1 创建模块文件-官网示例

  用文本编辑器在当前目录下创建fibo.py 文件

# Fibonacci numbers module
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

1.2 创建模块文件-简单示例

# mymodule.py

"""
This is a docstring for mymodule.
It provides an overview of the module's functionality.
"""

module_variable = 42

def my_function():
    """
    This is a docstring for my_function.
    It prints the module variable.
    """
    print(f"The module variable is: {module_variable}")

class MyClass:
    """
    This is a docstring for MyClass.
    It defines a simple class with an initialization method and a display method.
    """
    def __init__(self, value):
        self.value = value

    def display_value(self):
        print(f"Value from MyClass: {self.value}")

if __name__ == "__main__":
    print("This is the main program.")
    # 在这里可以添加模块被直接运行时执行的代码

  在这个例子中,mymodule.py文件定义了一个模块,包含了变量、函数、类等。这个模块的代码可以通过import语句在其他地方导入和使用。

1.3 以脚本方式执行模块

1.3.1 使用 python -m 命令行选项

  通过在命令行中使用 python -m命令,可以直接执行一个模块。这样,模块将被当作主程序执行,而不是作为一个库被导入。例如,假设有一个模块文件 mymodule.py

# mymodule.py

def my_function():
    print("This is my_function in mymodule.")

if __name__ == "__main__":
    print("This is executed when the module is run as a script.")
    my_function()

  在命令行中执行:

python -m mymodule

1.3.2 使用 if name == “main”: 语句块

  如前面的示例所示,在模块中使用if __name__ == "__main__": 语句块,可以在模块被直接运行时执行特定的代码。这使得模块既可以作为一个独立的脚本执行,也可以被其他模块导入和调用。

# mymodule.py

def my_function():
    print("This is my_function in mymodule.")

if __name__ == "__main__":
    print("This is executed when the module is run as a script.")
    my_function()

  在命令行中执行:

python mymodule.py

  这同样会执行 mymodule.py 中的if __name__ == "__main__": 语句块,并输出相应的结果:“This is executed when the module is run as a script.”。

1.4 模块搜索路径

  Python 模块搜索路径的顺序是先在导入模块的当前目录搜索,然后再在内置模块等其他路径中搜索。具体的搜索顺序如下:
  1)当前目录(当前工作目录): Python 解释器首先在运行脚本的当前目录中搜索要导入的模块。
  2)内置模块: 如果模块是 Python 的内置模块之一,解释器会直接加载它。
  3)PYTHONPATH 环境变量指定的路径: 如果 PYTHONPATH 环境变量包含了路径信息,解释器会在这些路径中搜索模块。
  4)site-packages 目录: 如果模块是第三方库中的模块,解释器会在 site-packages目录下搜索它。

1.5 “已编译的” Python文件

  为了快速加载模块,Python 把模块的编译版本缓存在__pycache__ 目录中,文件名为module.version.pycversion 对编译文件格式进行编码,一般是 Python 的版本号。例如,CPython 的 3.12 发行版中,spam.py 的编译版本缓存为__pycache__/spam.cpython-312.pyc。这种命名惯例让不同 Python 版本编译的模块可以共存。
  Python 对比编译版与源码的修改日期,查看编译版是否已过期,是否要重新编译。此进程完全是自动的。此外,编译模块与平台无关,因此,可在不同架构的系统之间共享相同的库。
  Python 在两种情况下不检查缓存。一,从命令行直接载入的模块,每次都会重新编译,且不储存编译结果;二,没有源模块,就不会检查缓存。为了让一个库能以隐藏源代码的形式分发(通过将所有源代码变为编译后的版本),编译后的模块必须放在源目录而非缓存目录中,并且源目录绝不能包含同名的未编译的源模块。
  一些小建议:
  在 Python 命令中使用-o-oo 开关,可以减小编译模块的大小。-o 去除断言语句,-oo去除断言语句和__doc__ 字符串。有些程序可能依赖于这些内容,因此,没有十足的把握,不要使用这两个选项。“优化过的”模块带有 opt-标签,并且文件通常会一小些。将来的发行版或许会改进优化的效果。
  从.pyc文件读取的程序不比从.py读取的执行速度快,.pyc文件只是加载速度更快。
  compileall模块可以为一个目录下的所有模块创建.pyc 文件。

1.6 标准模块

  在 Python 中,标准模块(Standard Module)指的是 Python 标准库(Standard Library)中的模块。标准库是 Python 安装包中内置的、由 Python 开发团队提供和维护的一组标准模块和包。这些模块涵盖了各种领域,包括文件 I/O、网络通信、文本处理、数学计算、日期时间处理等。
  标准库的模块是 Python 开发者在编写应用程序时经常需要用到的一系列工具,它们提供了丰富的功能和接口,可以大大提高开发效率。标准库的模块是由 Python 的开发者社区广泛使用和验证的,因此它们通常是稳定、可靠且经过充分测试的。
  一些常见的标准库模块包括:
    os:提供与操作系统交互的功能,如文件和目录操作。
    sys:提供与 Python 解释器交互的功能,例如命令行参数、标准输入输出。
    math:数学运算相关的功能。
    datetime:处理日期和时间。
    random:生成随机数。
    json:处理JSON格式的数据。
    urllib:用于处理URL。
    socket:网络编程相关的功能。
    sqlite3:SQLite数据库访问。
  使用标准库的好处在于,这些模块是与 Python 一同安装的,无需额外的安装步骤。

1.7 dir()函数

  dir()函数是一个内置函数,用于列出对象的属性和方法。它接受一个参数,即要检查的对象,然后返回一个包含对象所有属性和方法名称的列表。如果没有提供参数,dir()将返回当前作用域中的名称列表。
  dir([object])
    object(可选): 要检查的对象。如果省略该参数,则返回当前作用域中的名称列表。
    返回一个包含对象属性和方法名称的字符串列表。

print(dir()) # 示例1:查看当前作用域中的所有名称

print(dir(42)) # 示例2:查看整数对象的属性和方法

print(dir("Hello")) # 示例3:查看字符串对象的属性和方法

print(dir([1, 2, 3])) # 示例4:查看列表对象的属性和方法

# 示例5:查看自定义类的属性和方法
class MyClass:
    def __init__(self):
        self.my_attribute = "Hello"

    def my_method(self):
        print("Method called")

obj = MyClass()
print(dir(obj))
# dir() 用于查找模块定义的名称
import sys
dir(sys)

  运行效果:
Python的基础:模块(Modules)和包(Packages)详解_第1张图片
  dir() 不会列出内置函数和变量的名称。这些内容的定义在标准模块builtins中:

import builtins
dir(builtins) 

  运行效果:
Python的基础:模块(Modules)和包(Packages)详解_第2张图片

2. 包

  包是通过使用“带点号模块名”来构造 Python 模块命名空间的一种方式。 例如,模块名 A.B表示名为A 的包中名为 B的子模块。 就像使用模块可以让不同模块的作者不必担心彼此的全局变量名一样,使用带点号模块名也可以让 NumPyPillow 等多模块包的作者也不必担心彼此的模块名冲突。
  包的使用有助于组织大型项目,将相关的模块放在一起,提高代码的可维护性和可读性。
  以下是一个包的简单示例:
Python的基础:模块(Modules)和包(Packages)详解_第3张图片

  在这个例子中:
    my_package是一个包,因为它包含了一个 __init__.py 文件。
    module1.pymodule2.py my_package包的模块。
    subpackage是一个子包,因为它也包含了一个 __init__.py 文件。
    module3.pymodule4.pysubpackage的模块。

  在导入这些模块的时候,可以使用相对路径或绝对路径。以下是一些导入的示例:

# 导入包中的模块
import my_package.module1
from my_package import module2

# 导入子包中的模块
from my_package.subpackage import module3
from my_package.subpackage.module4 import some_function

# 使用别名
import my_package.module1 as m1

# 导入所有模块
from my_package import *

  my_package.module1 表示导入 my_package包中的 module1模块。
  from my_package import module2表示从my_package包中导入 module2模块。
  from my_package.subpackage import module3表示从my_package包的 subpackage子包中导入 module3 模块。
  from my_package.subpackage.module4 import some_function表示从my_package 包的 subpackage子包中导入 module4模块中的some_function函数。
  import my_package.module1 as m1 表示导入my_package 包中的module1模块,并给它起个别名 m1
  from my_package import * 表示导入my_package包中的所有模块。这种导入方式应该谨慎使用,因为它可能导致命名空间的污染。

3. Python导入模块

  Python提供了两种导入模块的方法:importfrom … import…。下面是两种不同的导入模块的示例:

"""
通过使用import math来导入math模块,并使用print(math.pi)输出圆周率常量π的值。另外,也可以使用from math import pi语句直接导入圆周率常量π,从而无需使用math.前缀。
"""
# 使用import导入模块
import math
print(math.pi)

# 使用from ... import导入模块
from math import pi
print(pi)

  有时候,需要将几个相关的模块结合在一起。Python提供了两种方法来实现模块组合:import module1, module2from module1 import func1, func2。下面是两种不同的模块组合示例:

"""
使用import math, random语句导入了math和random两个模块。
并使用print(math.pi)输出圆周率常量π的值,使用print(random.randint(1, 10))随机生成一个1到10之间的整数。
"""
# 使用import导入多个模块
import math, random

print(math.pi)
print(random.randint(1, 10))
"""
使用from math import pi, sqrt和from random import randint语句导入所需的函数和变量。
"""
# 使用from ... import导入多个函数
from math import pi, sqrt
from random import randint

print(pi)
print(randint(1, 10))

  模块可以组合在一起形成新的功能。一个模块可以调用另一个模块中的函数和类,并使用其他模块中的变量和数据结构。例如,下面的代码展示了如何使用os模块和sys模块来获取当前的工作目录:

import os
import sys

# 获取当前的工作目录
curdir = os.path.dirname(os.path.abspath(__file__))
# 输出当前的工作目录
print(curdir) 

你可能感兴趣的:(Python详解,python,模块,包,module,packages,路径搜索)