在模块和/或包中组织Python类

61 投票
3 回答
38453 浏览
提问于 2025-04-16 04:52

我喜欢Java的一个习惯,就是每个文件只放一个公共类。虽然有时候把多个公共类放在一个文件里也有它的好处。在我的情况下,我有几个实现了同一个接口的不同版本。如果我把它们放在不同的文件里,导入的时候就会出现重复的名字(或者让人误解的模块名):

import someConverter.SomeConverter

比如说,someConverter会是文件(和模块)的名字,而SomeConverter是类的名字。这样看起来就不太优雅。如果把所有的替代类放在一个文件里,导入的时候就会显得更有意义:

import converters.SomeConverter

不过我担心,如果把所有相关的类都放在一个模块文件里,文件会变得很大。那么在Python中,这种做法有什么最佳实践呢?每个文件放一个类是不常见的吗?

3 个回答

5

上面的解决方案不错,但在__init__.py里导入模块有个问题,就是会导致所有模块被加载两次(效率低下)。你可以在otherconverter.py的最后加一句打印语句,然后运行otherconverter.py。你会发现打印语句被执行了两次。

我更喜欢下面的方法。使用另一个叫“_converter”的包,把所有内容都定义在那里面。这样你的“converters.py”就变成了一个访问所有公共成员的接口。

* _converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

*  converters.py

其中converters.py

from _converters.someconverter import SomeConverter
from _converters.otherconverter import OtherConverter
...
...
...
converters = [SomeConverter, OtherConverter, ...]

正如之前提到的,这都是个人选择。有些做法是在包内定义一个模块“interface.py”,并在这里导入所有公共成员。如果你需要加载很多模块,应该选择效率而不是美观。

51

Zach的解决方案在Python 3上不太好用。这里有一个修复后的解决方案。

很多时候,这其实是个人喜好的问题。使用Python模块时,你可以选择把每个类放在不同的文件里,同时仍然可以使用 import converters.SomeConverter(或者 from converters import SomeConverter)来导入它们。

你的文件结构可以像这样:

* converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

然后在你的 __init__.py 文件中:

from converters.baseconverter import BaseConverter
from converters.otherconverter import OtherConverter
62

这很多时候其实是个人喜好的问题。使用Python模块时,你可以选择把每个类放在不同的文件里,这样仍然可以使用 import converters.SomeConverter(或者 from converters import SomeConverter)来导入它们。

你的文件结构可以像这样:

* converters
     - __init__.py
     - baseconverter.py
     - someconverter.py
     - otherconverter.py

然后在你的 __init__.py 文件里:

from baseconverter import BaseConverter
from otherconverter import OtherConverter

撰写回答