Spreading a class over multiple files
Gary Herron
gherron at digipen.edu
Sun Jun 5 03:18:08 EDT 2016
On 06/04/2016 11:55 PM, Mark Summerfield wrote:
> Sometimes I want to spread a class over multiple files.
There’s and easy way to do this in Python using what's called a Mixin
class and (multiple) inheritance:
(See https://en.wikipedia.org/wiki/Mixin for more information.)
In one file, say extras.py
class ExtraMethodsMixin:
def extra_1(...):
...
def extra_2(...):
...
In the main class file:
from extras import ExtraMethodsMixin
class MainClass(ExtraMethodsMixin):
def __init__(...):
...
# and so on
The result will be essentially the same as if all three methods were
defined in MainCLass.
Gary Herron
--
Dr. Gary Herron
Professor of Computer Science
DigiPen Institute of Technology
(425) 895-4418
>
> 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.py # _ModelOutput has the same structure so not shown
> import Lib
>
> __methods__ = [] # self is a Model
> register_method = Lib.register_method(__methods__)
>
> @register_method
> def config(self):
> ...
> So, that's the overall pattern of my solution.
>
> 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