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