views:

77

answers:

2

I need to extend the Networkx python package and add a few methods to the Graph class for my particular need

The way I thought about doing this is simplying deriving a new class say NewGraph, and adding the required methods.

However there are several other functions in networkx which create and return Graph objects (e.g. generate a random graph). I now need to turn these Graph objects into NewGraph objects so that I can use my new methods.

What is the best way of doing this? Or should I be tackling the problem in a completely different manner?

+1  A: 

If a function is creating Graph objects, you can't turn them into NewGraph objects.

Another option is for NewGraph is to have a Graph rather than being a Graph. You delegate the Graph methods to the Graph object you have, and you can wrap any Graph object into a new NewGraph object:

class NewGraph:
    def __init__(self, graph):
        self.graph = graph

    def some_graph_method(self, *args, **kwargs):
        return self.graph.some_graph_method(*args, **kwargs)
    #.. do this for the other Graph methods you need

    def my_newgraph_method(self):
        ....
Ned Batchelder
ThanksI read somewhere else that I can just change the __class__ attribute. e.g. MyRandomGraphObject.__class__ = NewGraph. And it does actually work. Bad practice?
zenna
+1  A: 

If you are just adding behavior, and not depending on additional instance values, you can assign to the object's __class__:

from math import pi

class Circle(object):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return pi * self.radius**2

class CirclePlus(Circle):
    def diameter(self):
        return self.radius*2

    def circumference(self):
        return self.radius*2*pi

c = Circle(10)
print c.radius
print c.area()
print repr(c)

c.__class__ = CirclePlus
print c.diameter()
print c.circumference()
print repr(c)

Prints:

10
314.159265359
<__main__.Circle object at 0x00A0E270>
20
62.8318530718
<__main__.CirclePlus object at 0x00A0E270>

This is as close to a "cast" as you can get in Python, and like casting in C, it is not to be done without giving the matter some thought. I've posted a fairly limited example, but if you can stay within the constraints (just add behavior, no new instance vars), then this might help address your problem.

Paul McGuire