61

I like the Java convention of having one public class per file, even if there are sometimes good reasons to put more than one public class into a single file. In my case I have alternative implementations of the same interface. But if I would place them into separate files, I'd have redundant names in the import statements (or misleading module names):

import someConverter.SomeConverter

whereas someConverter would be the file (and module) name and SomeConverter the class name. This looks pretty inelegant to me. To put all alternative classes into one file would lead to a more meaningful import statement:

import converters.SomeConverter

But I fear that the files become pretty large, if I put all related classes into a single module file. What is the Python best practise here? Is one class per file unusual?

asked Oct 1, 2010 at 19:58
1
  • 9
    By the time you're dealing with a project consisting of 10'000 classes, you'll be happy if you can find a (public) class by its file (and package) name instead of having to search the contents of all files.. that's probably the rationale why Java enforces that there is only one public class per file and that the file name must be the class name. Commented Oct 1, 2010 at 20:10

3 Answers 3

63

A lot of it is personal preference. Using python modules, you do have the option to keep each class in a separate file and still allow for import converters.SomeConverter (or from converters import SomeConverter)

Your file structure could look something like this:

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

and then in your __init__.py file:

from baseconverter import BaseConverter
from otherconverter import OtherConverter
answered Oct 1, 2010 at 20:07
Sign up to request clarification or add additional context in comments.

Comments

51

Zach's solution breaks on Python 3. Here is a fixed solution.

A lot of it is personal preference. Using python modules, you do have the option to keep each class in a separate file and still allow for import converters.SomeConverter (or from converters import SomeConverter)

Your file structure could look something like this:

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

and then in your __init__.py file:

from converters.baseconverter import BaseConverter
from converters.otherconverter import OtherConverter
answered Nov 6, 2012 at 20:25

4 Comments

How about just "from .baseconverter import BaseConverter" ?
Sorry for the late follow up, I've been out of touch with python in recent times, if someone can verify Michael's solution above then please feel free to edit my answer and add that as alternative. (Don't change my original because I think it's a matter of preference as to which one looks more readable so let's give the users both the options)
Michael's answer does work, but PEP 8 discourages relative imports. stackoverflow.com/questions/4209641/…
@JasonPearson Not anymore, explicit relative imports are fine for intra-package imports: mail.python.org/pipermail/python-dev/2010-October/104476.html
5

The above solutions are good, but the problem with importing modules in __init__.py is that this will cause all the modules to be loaded twice(inefficient). Try adding a print statement at the end of otherconverter.py and run otherconverter.py. (You'll see that the print statement is executed twice)

I prefer the following. Use another package with name "_converter" and define everything there. And then your "converters.py" becomes the interface for accessing all public members

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

where converters.py is

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

And as the previous solutions mentioned, it is a personal choice. A few practices involve defining a module "interface.py" within the package and importing all public members here. If you have many modules to load, you should choose efficiency over aesthetics.

answered Oct 9, 2020 at 16:37

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.