Main Content

Should Python classes each be in their own file?

Archive - Originally posted on "The Horse's Mouth" - 2010-07-27 06:32:36 - Graham Ellis

Should classes each be defined in a file of their own? In Java, unless you're making a use of inner classes, you're coerced into writing one class per file. In C++, you'll typically have the code for a class in one source file and the headers in another, as other schemes are impractical to use and maintain. But in many other languages - and the example I've chosen is Python - there's nothing stopping you defining multiple classes in the same file. You can ... but should you???

One of the big gains from using objects is that it allows you to compartmentalize your logic - putting everything that relates to a film into one class, and everything that relates to a cycle race in another. There's then no "leak" between the namespaces - no confusion when you say milkrace.getlength() or shrek3.getlength() as to which logic you're running. And there's the ability for you to have separate files, maintainance team and schedules for the various types of object / classes. But there is a bit of a "downer" it that it's pretty hard to work out what you can do with an object sometimes as it inherits through a web of classes that are based on other classes, picking up cascading code (bit like the problems with "where did THAT font come from" you may have if you're using CSS / Cascading style sheets)

Where you've got a group of classes which are (a) maintained by the same person, (b) maintained on the same schedule and (c) going to be used together ... then there's no good reason I can see that you should separate each of them out into a file of its own. Go ahead and combine them!. The small gains you might make will be a consistency of naming with all classes being in files of the same name, but having them in separate files would lead to a needless layer of files. You have only to look at Java to realise what an issue this can be in the Java world, where the files are often bundled up into another structure called a jar file ...

I have put a complete class structure into a single file in an example [here]. There are four classes with three layers of inheritance joining them - so they will naturally fall together into the same application (you can't use a taxi without a travel ... which you can't use without an event!).




If you want to find out what you can do on your object in Python, you can use the dir function. Using the code example above, I decided to find out what methods I could use on a taxi ... and here's how I did it:

wizard:python graham$ python
Python 2.6.1 (r261:67515, Feb 11 2010, 15:47:53)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from teapot import *
>>> ap = taxi("Seend","13:15",5)
>>> dir(ap)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'celebrate', 'destiny', 'getcapacity', 'getdestiny', 'gettime', 'seats', 'time']
>>> ^D
wizard:python graham$


To do a similar thing in Java, use the javap utility with the class file in which the object type you wish to examine available in your class path:

wizard:java graham$ javap gowdie/Isobel
Compiled from "Isobel.java"
public class gowdie.Isobel extends java.lang.Object{
  float age;
  float factor;
  public java.lang.String name;
  static int nanimals;
  public gowdie.Isobel(int, int);
  public gowdie.Isobel(java.lang.String, int, int);
  public gowdie.Isobel(java.lang.String, int);
  public float getEffAge();
  public static int getCount();
  static {};
}
 
wizard:java graham$


(See [here] for more about Isobel Gowdie!)