Tobias Pfeiffer wrote:
I want to write a package of modules that deal with mathematical
graphs. So my plan is to have a main.py file where the basic operations
are done, like reading the file and creating an adjacence list and all
that. In this main.py file, there is created a Graph class with several
methods, such as deg(v) or delvertex(v).
And then, for all of the other things one can do with a graph, I want
to code other modules, e.g. a file euler.py for finding an Euler way
through the graph, that extends the class by the method eulerway(). I
know that I can do something like
# graphtools/euler.py
import main
class Graph(main.Graph):
def eulerway(self):
[...]
and then the Graph class imported from euler.py will have both the old
and the new methods. But what can I do if I want the end user to be
able to combine several modules and I don't know in which order he will
do? For example, by
import graphtools.main, graphtools.hamilton
I can do the thingy described above, but what is with something like
import graphtools.hamilton, graphtools.euler
? In that case I want the class to have all of the methods defined in
the modules. How do I realize that in the best way?
#__init__.py
class Graph(object):
def deg(self, v):
# your code
#euler.py
class EulerMixin(object):
def eulerway(self):
# your code
#hamilton.py
class HamiltonMixin(object):
def whatever(self):
# your code
The above are all in the graphtools package directory.
Now a sample usage:
#application.py
import graphtools
from graphtools import euler, hamilton
class Graph(graphtools.Graph, euler.EulerMixin, hamilton.HamiltonMixin):
pass
The XXXMixin classes are not for standalone use, they should only call but
not override the Graph methods. As long as the different mixins are
orthogonal, i. e. do not affect each other all should be fine.
Alternatively you can derive the hamilton/euler variants from
graphtools.Graph. You must then design the different classes with
cooperation in mind, as demonstrated below with three initialization
routines which are assumed to be run only once:
#__init__.py
class Graph(object):
def __init__(self):
self.init()
def init(self):
print "init main"
def deg(self, v):
print "deg"
#euler.py
import graphtools
class EulerGraph(graphtools.Graph):
def eulerway(self):
print "eulerway"
def init(self):
print "init euler"
super(EulerGraph, self).init()
#hamilton.py
import graphtools
class HamiltonGraph(graphtools.Graph):
def whatever(self):
print "whatever"
def init(self):
print "init hamilton"
super(HamiltonGraph, self).init()
#usegraphtools.py
import graphtools
from graphtools import euler, hamilton
class Graph(euler.EulerGraph, hamilton.HamiltonGraph):
pass
g = Graph()
g.eulerway()
g.whatever()
g.deg(1)
Output:
init euler
init hamilton
init main
eulerway
whatever
deg
Peter