Spread a class over multiple files

Mark Summerfield list at qtrac.plus.com
Sun Jun 5 02:47:31 EDT 2016


Sometimes I want to spread a class over multiple files.

My primary use case is when I create a "Model" class to reflect an entire SQL database. I want a model instance to provide a single point of access to the database, but the database has many tables each requiring its own methods since they differ in their structure, purpose, validation needs, etc.

A secondary use case is when I create "MainWindow" classes in GUI programming and have lots of methods to reflect all the actions (e.g., menu options and toolbar actions, plus interaction with the main widget(s)).

To meet these needs I've devised an approach that I think is easy to use and understand and which doesn't use any tricky or hard to maintain code.

My question is -- are there nicer/better ways to achieve this?

Here's a summary of my approach. A fuller discussion is on my website:
https://www.qtrac.eu/pyclassmulti.html

# Lib.py
# This provides the two functions (both decorators) used to support my approach
def add_methods_from(*modules):
    def decorator(Class):
        for module in modules:
            for method in getattr(module, "__methods__"):
                setattr(Class, method.__name__, method)
        return Class
    return decorator

def register_method(methods): # A decorator used purely for its side-effect
    def register_method(method):
        methods.append(method)
        return method # Unchanged and not strictly necessary
    return register_method

# Model.py
# This provides my model but some methods are in separate files
import Lib
import _ModelConfig
import _ModelOutput

@Lib.add_methods_from(_ModelConfig, _ModelOutput)
class Model:
    ...
    def small_method(self):
        ...

# _ModelConfig # _ModelOutput has the same structure so not shown
import Lib
__methods__ = [] # self is a Model

@Lib.register_method(__methods__)
def config(self):
    ...

So, that's the overall pattern of my solution. I know that I could use functools partial, e.g.,

register_method = functools.partial(Lib.register_method, __methods__)

...

@register_method
def config(self):
    ...

So, is there a nicer/better way? Could I cleanly avoid the explicit imports (e.g., import _ModelConfig), without resorting to stack frame hacks or similar?


More information about the Python-list mailing list