Python3 module and packagetutorial

Learning Python3 in module化programming, includingmodule and package creation, using and 组织

module化programmingIntroduction

module化programming is a将 big 型程序分解 for 更 small , 更可management 部分 method. in Pythonin, 这些部分被称 for module (Module) and package (Package) .

module化programming 优点including:

module concepts and using

what is module?

in Pythonin, module is a package含Python定义 and 语句 file. module可以package含function, class and variable, 也可以package含可执行 code. modulefile名就 is module名加 on .py after 缀.

creationmodule

要creation一个module, 只需creation一个package含Pythoncode .pyfile. 例such as, creation一个名 for mymodule.py file:

# mymodule.py

def greet(name):
    """向某人问 good """
    return f"Hello, {name}!"

def add(a, b):
    """计算两个数  and """
    return a + b

# module级variable
PI = 3.14159
version = "1.0.0"

# 可执行code
if __name__ == "__main__":
    print("This is mymodule.py")
    print(f"PI = {PI}")
    print(f"Version = {version}")

importmodule

要usingmodulein code, 需要先importmodule. Pythonproviding了 many 种importmodule 方式:

1. import整个module

import mymodule

# usingmodulein function
print(mymodule.greet("Alice"))  # 输出: Hello, Alice!
print(mymodule.add(10, 20))  # 输出: 30

# usingmodulein variable
print(mymodule.PI)  # 输出: 3.14159
print(mymodule.version)  # 输出: 1.0.0

2. importmodule并指定别名

import mymodule as mm

# using别名访问modulein  in 容
print(mm.greet("Bob"))  # 输出: Hello, Bob!
print(mm.add(5, 7))  # 输出: 12
print(mm.PI)  # 输出: 3.14159

3. from moduleinimportspecific in 容

from mymodule import greet, PI

# 直接usingimport function and variable
print(greet("Charlie"))  # 输出: Hello, Charlie!
print(PI)  # 输出: 3.14159

# 注意: add and version未import, 不能直接using
# print(add(2, 3))  # NameError: name 'add' is not defined
# print(version)  # NameError: name 'version' is not defined

4. from moduleinimport所 has in 容

from mymodule import *

# 直接usingmodulein 所 has  in 容
print(greet("David"))  # 输出: Hello, David!
print(add(3, 4))  # 输出: 7
print(PI)  # 输出: 3.14159
print(version)  # 输出: 1.0.0

注意: 虽然from module import *很方便, 但通常不推荐using, 因 for 它会importmodulein 所 has 名称, 可能导致命名conflict.

package concepts and using

what is package?

package is a package含 many 个module Table of Contents, 它可以helping我们组织相关 module. packageTable of Contents必须package含一个名 for __init__.py file, 这个file可以 is 空 , 也可以package含package级别 初始化code.

creationpackage

要creation一个package, 需要按照以 under 步骤operation:

  1. creation一个Table of Contentsserving aspackage 根Table of Contents
  2. in 该Table of Contentsincreation一个__init__.pyfile
  3. in 该Table of Contentsincreationmodulefile

例such as, creation一个名 for mypackage package:

# Table of Contentsstructure
# mypackage/
# ├── __init__.py
# ├── module1.py
# └── module2.py

# mypackage/__init__.py
__version__ = "1.0.0"

# importpackagein module
from . import module1
from . import module2

# mypackage/module1.py
def func1():
    return "This is func1 from module1"

# mypackage/module2.py
def func2():
    return "This is func2 from module2"

usingpackage

usingpackage 方式 and usingmoduleclass似:

1. import整个package

import mypackage

# usingpackagein module
print(mypackage.module1.func1())  # 输出: This is func1 from module1
print(mypackage.module2.func2())  # 输出: This is func2 from module2

# usingpackage级别 variable
print(mypackage.__version__)  # 输出: 1.0.0

2. importpackage并指定别名

import mypackage as mp

print(mp.module1.func1())  # 输出: This is func1 from module1
print(mp.module2.func2())  # 输出: This is func2 from module2
print(mp.__version__)  # 输出: 1.0.0

3. from packageinimportspecificmodule

from mypackage import module1

print(module1.func1())  # 输出: This is func1 from module1

# 注意: module2未import, 不能直接using
# print(module2.func2())  # NameError: name 'module2' is not defined

4. from package moduleinimportspecificfunction

from mypackage.module1 import func1
from mypackage.module2 import func2

print(func1())  # 输出: This is func1 from module1
print(func2())  # 输出: This is func2 from module2

module搜索path

当Pythonimport一个module时, 它会 in 以 under 位置按顺序搜索:

  1. 当 before Table of Contents
  2. PYTHONPATHenvironmentvariablein列出 Table of Contents
  3. Python标准libraryTable of Contents
  4. 任何.pthfilein指定 Table of Contents

可以usingsysmodule查看 and modifymodule搜索path:

import sys

# 查看当 before module搜索path
print("Module search paths:")
for path in sys.path:
    print(f"- {path}")

# 添加 new  搜索path
sys.path.append("/path/to/your/modules")
print("\nAfter adding new path:")
print(sys.path[-1])

相 for import and 绝 for import

绝 for import

绝 for import is 指 from package 根Table of Contents开始指定importpath. 例such as:

# 绝 for import
from mypackage.module1 import func1
import mypackage.module2

相 for import

相 for import is 指using点号表示当 before package and 父package import方式. 相 for import只能 in package in 部using, 不能 in 脚本inusing.

# fake设我们 in mypackagepackage in 部

# import同一packagein othermodule
from . import module2  # import当 before packagein module2
from .module2 import func2  # import当 before packageinmodule2 func2

# import父packagein module
from .. import other_module  # import父packagein other_module
from ..other_module import func  # import父packageinother_module func

# import兄弟packagein module
from ..sibling_package import module  # import兄弟packagein module

相 for importin 点号含义:

module __name__property

每个module都 has 一个__name__property, 它 值取决于module is such as何被using :

这个property通常用于 in module被直接run时执行一些code, 而 in module被import时不执行这些code:

# mymodule.py

def main():
    print("This is the main function")

if __name__ == "__main__":
    # 当module被直接run时执行
    print("Running as a script")
    main()
else:
    # 当module被import时执行
    print("Being imported as a module")

当直接runmymodule.py时:

$ python mymodule.py
Running as a script
This is the main function

当importmymodule时:

>>> import mymodule
Being imported as a module
>>> mymodule.main()
This is the main function

实践case: creation一个数学toolpackage

creation一个名 for math_tools package, package含以 under module:

# Table of Contentsstructure
# math_tools/
# ├── __init__.py
# ├── basic.py
# ├── geometry.py
# └── statistics.py

# math_tools/__init__.py
__version__ = "1.0.0"

# export常用function
from .basic import add, subtract, multiply, divide
from .geometry import circle_area, rectangle_area, triangle_area
from .statistics import mean, median, mode

# math_tools/basic.py
def add(a, b):
    """计算两个数  and """
    return a + b

def subtract(a, b):
    """计算两个数 差"""
    return a - b

def multiply(a, b):
    """计算两个数 积"""
    return a * b

def divide(a, b):
    """计算两个数 商"""
    if b == 0:
        raise ValueError("除数不能 for 零")
    return a / b

# math_tools/geometry.py
import math

def circle_area(radius):
    """计算圆 面积"""
    return math.pi * radius ** 2

def rectangle_area(length, width):
    """计算矩形 面积"""
    return length * width

def triangle_area(base, height):
    """计算三角形 面积"""
    return 0.5 * base * height

# math_tools/statistics.py
def mean(numbers):
    """计算平均值"""
    if not numbers:
        return 0
    return sum(numbers) / len(numbers)

def median(numbers):
    """计算in位数"""
    if not numbers:
        return 0
    sorted_numbers = sorted(numbers)
    n = len(sorted_numbers)
    if n % 2 == 0:
        return (sorted_numbers[n//2 - 1] + sorted_numbers[n//2]) / 2
    else:
        return sorted_numbers[n//2]

def mode(numbers):
    """计算众数"""
    if not numbers:
        return None
    count = {}
    for num in numbers:
        count[num] = count.get(num, 0) + 1
    max_count = max(count.values())
    modes = [num for num, cnt in count.items() if cnt == max_count]
    return modes[0] if len(modes) == 1 else modes

# test数学toolpackage
if __name__ == "__main__":
    print("Testing math_tools package")
    print(f"Version: {__version__}")
    
    # testbasic运算
    print("\nBasic operations:")
    print(f"3 + 4 = {add(3, 4)}")
    print(f"10 - 6 = {subtract(10, 6)}")
    print(f"5 * 7 = {multiply(5, 7)}")
    print(f"12 / 3 = {divide(12, 3)}")
    
    # test几何计算
    print("\nGeometry:")
    print(f"Circle area (radius=5): {circle_area(5):.2f}")
    print(f"Rectangle area (5x3): {rectangle_area(5, 3)}")
    print(f"Triangle area (base=4, height=6): {triangle_area(4, 6)}")
    
    # teststatistics计算
    print("\nStatistics:")
    data = [1, 2, 3, 4, 5, 5, 6, 7, 8, 9]
    print(f"Data: {data}")
    print(f"Mean: {mean(data)}")
    print(f"Median: {median(data)}")
    print(f"Mode: {mode(data)}")

互动练习

练习1: creation一个toolmodule

creation一个名 for utils.py module, package含以 under function:

  • is_prime(n): 判断一个数 is 否 for 质数
  • factorial(n): 计算一个数 阶乘
  • fibonacci(n): 生成斐波那契数列 before n个数

然 after creation一个脚本import并test这些function.

练习2: creation一个学生managementpackage

creation一个名 for student_management package, package含以 under module:

  • models.py: package含学生class 定义
  • database.py: package含学生data store and 读取function
  • utils.py: package含学生data processingfunction

然 after creation一个脚本import并test这个package.

练习3: understandingmodule __name__property

creation一个名 for test_module.py module, package含以 under in 容:

  • 一个functionsay_hello(), 打印"Hello from test_module"
  • usingif __name__ == "__main__":语句, 当module被直接run时打印"Running test_module directly"

然 after creation两个脚本:

  • 一个直接runtest_module.py
  • 一个importtest_module并调用say_hello()function

观察两种run方式 输出diff.