Python如何将将模块分割成多个文件

作者:David Beazley 时间:2022-03-26 15:03:18 

问题

你想将一个模块分割成多个文件。但是你不想将分离的文件统一成一个逻辑模块时使已有的代码遭到破坏。

解决方案

程序模块可以通过变成包来分割成多个独立的文件。考虑下下面简单的模块:


# mymodule.py
class A:
 def spam(self):
   print('A.spam')

class B(A):
 def bar(self):
   print('B.bar')

假设你想mymodule.py分为两个文件,每个定义的一个类。要做到这一点,首先用mymodule目录来替换文件mymodule.py。 这这个目录下,创建以下文件:


mymodule/
 __init__.py
 a.py
 b.py

在a.py文件中插入以下代码:


# a.py
class A:
 def spam(self):
   print('A.spam')

在b.py文件中插入以下代码:


# b.py
from .a import A
class B(A):
 def bar(self):
   print('B.bar')

最后,在 __init__.py 中,将2个文件粘合在一起:


# __init__.py
from .a import A
from .b import B

如果按照这些步骤,所产生的包MyModule将作为一个单一的逻辑模块:


>>> import mymodule
>>> a = mymodule.A()
>>> a.spam()
A.spam
>>> b = mymodule.B()
>>> b.bar()
B.bar
>>>

讨论

在这个章节中的主要问题是一个设计问题,不管你是否希望用户使用很多小模块或只是一个模块。举个例子,在一个大型的代码库中,你可以将这一切都分割成独立的文件,让用户使用大量的import语句,就像这样:


from mymodule.a import A
from mymodule.b import B
...

这样能工作,但这让用户承受更多的负担,用户要知道不同的部分位于何处。通常情况下,将这些统一起来,使用一条import将更加容易,就像这样:


from mymodule import A, B

对后者而言,让mymodule成为一个大的源文件是最常见的。但是,这一章节展示了如何合并多个文件合并成一个单一的逻辑命名空间。 这样做的关键是创建一个包目录,使用 __init__.py 文件来将每部分粘合在一起。

当一个模块被分割,你需要特别注意交叉引用的文件名。举个例子,在这一章节中,B类需要访问A类作为基类。用包的相对导入 from .a import A 来获取。

整个章节都使用包的相对导入来避免将顶层模块名硬编码到源代码中。这使得重命名模块或者将它移动到别的位置更容易

作为这一章节的延伸,将介绍延迟导入。如图所示,__init__.py文件一次导入所有必需的组件的。但是对于一个很大的模块,可能你只想组件在需要时被加载。 要做到这一点,__init__.py有细微的变化:


# __init__.py
def A():
 from .a import A
 return A()

def B():
 from .b import B
 return B()

在这个版本中,类A和类B被替换为在第一次访问时加载所需的类的函数。对于用户,这看起来不会有太大的不同。 例如:


>>> import mymodule
>>> a = mymodule.A()
>>> a.spam()
A.spam
>>>

延迟加载的主要缺点是继承和类型检查可能会中断。你可能会稍微改变你的代码,例如:


if isinstance(x, mymodule.A): # Error
...

if isinstance(x, mymodule.a.A): # Ok
...

延迟加载的真实例子, 见标准库 multiprocessing/__init__.py 的源码.

来源:https://python3-cookbook.readthedocs.io/zh_CN/latest/c10/p04_split_module_into_multiple_files.html

标签:Python,模块,文件
0
投稿

猜你喜欢

  • Python数据分析之Matplotlib数据可视化

    2022-03-05 06:37:48
  • python编程实现清理微信重复缓存文件

    2022-06-20 02:12:12
  • 微信小程序实现图片上传、删除和预览功能的方法

    2023-09-20 08:54:30
  • 在Python中使用AOP实现Redis缓存示例

    2021-09-12 11:18:45
  • 《web信息架构》——分类方式

    2009-11-27 19:16:00
  • Python设计模式编程中的备忘录模式与对象池模式示例

    2023-02-06 05:48:43
  • Python获取一个用户名的组ID过程解析

    2021-09-04 15:40:05
  • python sklearn包——混淆矩阵、分类报告等自动生成方式

    2022-05-29 12:19:27
  • Python对多个sheet表进行整合实例讲解

    2021-01-15 06:18:24
  • 超轻量级MSXML多功能测试程序

    2009-05-19 12:38:00
  • python解析基于xml格式的日志文件

    2022-11-08 21:26:31
  • SQL Server索引管理的六大铁律

    2009-03-25 14:05:00
  • Javascript的匿名函数

    2008-05-07 13:33:00
  • golang的httpserver优雅重启方法详解

    2023-08-06 00:22:41
  • Python列表删除元素del、pop()和remove()的区别小结

    2021-12-02 07:32:41
  • Python 多线程,threading模块,创建子线程的两种方式示例

    2021-06-29 15:49:32
  • 深入理解Python3中的http.client模块

    2021-05-26 04:12:34
  • python pycurl验证basic和digest认证的方法

    2022-12-17 23:01:15
  • 解决Python 遍历字典时删除元素报异常的问题

    2023-11-17 04:06:47
  • Python的动态重新封装的教程

    2023-08-23 15:26:39
  • asp之家 网络编程 m.aspxhome.com