Learning Python3 in module化programming, includingmodule and package creation, using and 组织
module化programming is a将 big 型程序分解 for 更 small , 更可management 部分 method. in Pythonin, 这些部分被称 for module (Module) and package (Package) .
module化programming 优点including:
in Pythonin, module is a package含Python定义 and 语句 file. module可以package含function, class and variable, 也可以package含可执行 code. modulefile名就 is module名加 on .py after 缀.
要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}")
要usingmodulein code, 需要先importmodule. Pythonproviding了 many 种importmodule 方式:
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
import mymodule as mm
# using别名访问modulein in 容
print(mm.greet("Bob")) # 输出: Hello, Bob!
print(mm.add(5, 7)) # 输出: 12
print(mm.PI) # 输出: 3.14159
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
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 is a package含 many 个module Table of Contents, 它可以helping我们组织相关 module. packageTable of Contents必须package含一个名 for __init__.py file, 这个file可以 is 空 , 也可以package含package级别 初始化code.
要creation一个package, 需要按照以 under 步骤operation:
__init__.pyfile例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 方式 and usingmoduleclass似:
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
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
from mypackage import module1
print(module1.func1()) # 输出: This is func1 from module1
# 注意: module2未import, 不能直接using
# print(module2.func2()) # NameError: name 'module2' is not defined
from mypackage.module1 import func1
from mypackage.module2 import func2
print(func1()) # 输出: This is func1 from module1
print(func2()) # 输出: This is func2 from module2
当Pythonimport一个module时, 它会 in 以 under 位置按顺序搜索:
可以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 is 指 from package 根Table of Contents开始指定importpath. 例such as:
# 绝 for import
from mypackage.module1 import func1
import mypackage.module2
相 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 点号含义:
.: 当 before package..: 父package...: 祖父package, 以此class推每个module都 has 一个__name__property, 它 值取决于module is such as何被using :
__name__ 值 for "__main__"__name__ 值 for module 名称这个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
creation一个名 for math_tools package, package含以 under module:
basic.py: package含basic数学运算functiongeometry.py: package含几何计算functionstatistics.py: package含statistics计算function# 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)}")
creation一个名 for utils.py module, package含以 under function:
is_prime(n): 判断一个数 is 否 for 质数factorial(n): 计算一个数 阶乘fibonacci(n): 生成斐波那契数列 before n个数然 after creation一个脚本import并test这些function.
creation一个名 for student_management package, package含以 under module:
models.py: package含学生class 定义database.py: package含学生data store and 读取functionutils.py: package含学生data processingfunction然 after creation一个脚本import并test这个package.
creation一个名 for test_module.py module, package含以 under in 容:
say_hello(), 打印"Hello from test_module"if __name__ == "__main__":语句, 当module被直接run时打印"Running test_module directly"然 after creation两个脚本:
test_module.pytest_module并调用say_hello()function观察两种run方式 输出diff.