Coding an extendable class

Discussion in 'Python' started by Tobias Pfeiffer, Dec 30, 2003.

  1. Hi!

    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?

    Bye
    Tobias

    --
    please send any mail to botedesschattens(at)web(dot)de
    Tobias Pfeiffer, Dec 30, 2003
    #1
    1. Advertising

  2. Tobias Pfeiffer

    Jeff Epler Guest

    Python sometimes uses "mixin" classes -- see the SocketServer module for
    one example in a core module.

    So main.Graph would be the real graph class, and
    graphtools.hamilton.HamiltonMixin would be one mixin:
    class MyGraph(main.Graph, hamilton.HamiltonMixin):
    pass
    You could use new.classobj to create a class object with a given list
    of mixins at runtime (untested):
    # In Main
    _graph_classes = []

    def add_mixin(m):
    _graph_classes.append(m)
    global Graph
    Graph = new.classobj("Graph", _graph_classes, {})

    add_mixin(main._Graph)

    # In each module that defines a new mixin
    class HamiltonianMixin:
    pass
    main.add_mixin(HamiltonianMixin)
    however, having the exact nature of main.Graph depend on what other
    modules have been imported is not what most Python users would expect.
    I prefer the solution of having the user list mixins by creating a
    "personalized" graph class.

    Jeff
    Jeff Epler, Dec 30, 2003
    #2
    1. Advertising

  3. Tobias Pfeiffer

    Peter Otten Guest

    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
    Peter Otten, Dec 30, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ivan Vecerina

    Re: Extendable envelope/letter idiom

    Ivan Vecerina, Jun 24, 2003, in forum: C++
    Replies:
    0
    Views:
    1,112
    Ivan Vecerina
    Jun 24, 2003
  2. Replies:
    1
    Views:
    880
    Oliver Wong
    Jul 10, 2006
  3. sapzz
    Replies:
    1
    Views:
    105
    John Carter
    Feb 7, 2006
  4. sapzz
    Replies:
    0
    Views:
    69
    sapzz
    Feb 6, 2006
  5. Mark

    Extendable factory

    Mark, May 29, 2012, in forum: C++
    Replies:
    12
    Views:
    693
Loading...

Share This Page