My code-template
First: I like to have things organized in a specific way. When I write a class, the structure of the code starts like so:
# Comment(s) for the file, may or may not include # source-control macros, but should include the file-name, at the very # least: # Namespace.Path (file-name.py) """Doc-string providing a summary of the package/module""" # Define __all__ list, so that we can use "from MODULE/PACKAGE import *" # syntax elsewhere. __all__ = [] ######################################################################## # Required imports # ######################################################################## # import os, sys # from MODULE import ITEMS ######################################################################## # Package constants # ######################################################################## # Any package- or module-level constants that need to be defined. # Constants that need to be accessed outside the scope of the file they # are defined in should have an __all__ entry as well: # Summary of constant CONSTANTNAME = 'CONSTANT_VALUE' __all__ += [ 'CONSTANTNAME' ] ######################################################################## # Custom Exceptions # ######################################################################## class CustomException( Exception ): """Custom exception to be raised when SOME_CONDITION_OCCURS.""" pass __all__ += [ 'CustomException' ] ######################################################################## # Definitions of (nominal) interfaces and abstract classes # ######################################################################## class IInterfaceName( object ): """Nominal interface, provides functional requirements for objects that CAN_DO_WHATEVER""" ########################### # Class Attributes # ########################### ########################### # Class Property Getters # ########################### ########################### # Class Property Setters # ########################### ########################### # Class Property Deleters # ########################### ########################### # Class Properties # ########################### ########################### # Object Constructor # ########################### ########################### # Object Destructor # ########################### ########################### # Class Methods # ########################### ########################### # Static Class Methods # ########################### pass __all__ += [ 'IInterfaceName' ] class BaseClassName( object ): """Nominal abstract class, provides baseline functionality and interface requirements for objects that CAN_DO_WHATEVER""" ########################### # Class Attributes # ########################### ########################### # Class Property Getters # ########################### ########################### # Class Property Setters # ########################### ########################### # Class Property Deleters # ########################### ########################### # Class Properties # ########################### ########################### # Object Constructor # ########################### ########################### # Object Destructor # ########################### ########################### # Class Methods # ########################### ########################### # Static Class Methods # ########################### pass __all__ += [ 'BaseClassName' ] ######################################################################## # Instantiable classes # ######################################################################## class ClassName( object ): """CLASS_SUMMARY""" ########################### # Class Attributes # ########################### ########################### # Class Property Getters # ########################### ########################### # Class Property Setters # ########################### ########################### # Class Property Deleters # ########################### ########################### # Class Properties # ########################### ########################### # Object Constructor # ########################### ########################### # Object Destructor # ########################### ########################### # Class Methods # ########################### ########################### # Static Class Methods # ########################### pass __all__ += [ 'ClassName' ]
I generally try to keep class attributes, property-getter/-setter and -deleter functions, properties, and class methods alphabetized within their commented sections, if only because I haven't really learned how to use Git yet, and alphabetizing them allows changes to be more easily understood in other source-control systems.
Use of "nominal" interfaces and abstract classes
I know that Python provides a package that allows for the implementation of interfaces and abstract classes (the
abc
package), but I'm unconvinced that it's the way to go. Since the base Python language-structure doesn't really have a formal interface or abstract-class mechanism, and I discovered the abc
package late, I'd more or less gotten into the habit of just writing classes that behaved somewhat like an interface or abstract class would:- Instantiation of a nominal interface or abstract class would raise an error (I typically use a
NotImplementedError
); - Nominally-abstract methods would be defined to raise an error (again, a
NotImplementedError
) if they were called from a derived-class instance that did not override them; - Concrete methods in a nominal abstract class would have actual implementation, and would rarely (never, in my experience) require an active check to see if they were being called on an instance of the abstract class, since it couldn't be instantiated.
abc
package does much of the same sort of thing, though in a different manner (and one that I'll freely admit I don't understand the inner workings of). The primary difference between the two is that my approach doesn't require that a derived class have all of the required methods during development, which I find to be less troublesome.At the same time, my approach does require more unit-testing, potentially, but since most of the unit-testing that I've found necessary using my approach are cases that I would also be testing using the the
abc
package's capabilities, it feels like a wash to me.Property Getters, Setters and Deleters, and Properties
There is a standard (presumably "Pythonic") way of using
@property
decorators to define object properties - see docs.python.org/.../functions.html#property. My experience with this decorator structure has caused minor but annoying issues in my code in the past, when I have needed to implement additional decoration on a getter/setter function. As a result, I tend to prefer breaking out the property-getter/-setter/-deleter functions separately (which I'd do in either case), and explicitly set the property using the built-in property
function, rather than decorating the individual functions.Documentation decorators
Though I haven't used them here (because I'm going to blog about them later), I have a set of documentation-decorators that I use with some frequency that will eventually allow generation of HTML or LaTeX (and thus PDF) API-documentation.