Cast base class to derived class python (or more pythonic way of extending classes)?

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 20 62.8318530718.

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 20 62.8318530718 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.

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): ....

Thanks I read somewhere else that I can just change the class attribute. E.g. MyRandomGraphObject.

__class__ = NewGraph. And it does actually work. Bad practice?

– zenna Aug 12 '10 at 1:35.

Here's how to "magically" replace a class in a module with a custom-made subclass without touching the module. It's only a few extra lines from a normal subclassing procedure, and therefore gives you (almost) all the power and flexibility of subclassing as a bonus. For instance this allows you to add new attributes, if you wish.

Import networkx as nx class NewGraph(nx. Graph): def __getattribute__(self, attr): "This is just to show off, not needed" print "getattribute %s" % (attr,) return nx.Graph. __getattribute__(self, attr) def __setattr__(self, attr, value): "More showing off." print " setattr %s = %r" % (attr, value) return nx.Graph.

__setattr__(self, attr, value) def plot(self): "A convenience method" import matplotlib. Pyplot as plt nx. Draw(self) plt.show() So far this is exactly like normal subclassing.

Now we need to hook this subclass into the networkx module so that all instantiation of nx. Graph results in a NewGraph object instead. Here's what normally happens when you instantiate an nx.

Graph object with nx.Graph() 1. Nx.Graph. __new__(nx.

Graph) is called 2. If the returned object is a subclass of nx. Graph, __init__ is called on the object 3.

The object is returned as the instance We will replace nx.Graph. __new__ and make it return NewGraph instead.In it, we call the __new__ method of object instead of the __new__ method of NewGraph, because the latter is just another way of calling the method we're replacing, and would therefore result in endless recursion. Def __new__(cls): if cls == nx.

Graph: return object. __new__(NewGraph) return object. __new__(cls) # We substitute the __new__ method of the nx.

Graph class # with our own.Nx.Graph. __new__ = staticmethod(__new__) # Test if it works graph = nx.generators. Random_graphs.

Fast_gnp_random_graph(7, 0.6) graph.plot() In most cases this is all you need to know, but there is one gotcha. Our overriding of the __new__ method only affects nx. Graph, not its subclasses.

For example, if you call nx. Gn_graph, which returns an instance of nx. DiGraph, it will have none of our fancy extensions.

You need to subclass each of the subclasses of nx. Graph that you wish to work with and add your required methods and attributes. Using mix-ins may make it easier to consistently extend the subclasses while obeying the DRY principle.

Though this example may seem straightforward enough, this method of hooking into a module is hard to generalize in a way that covers all the little problems that may crop up. I believe it's easier to just tailor it to the problem at hand. For instance, if the class you're hooking into defines its own custom __new__ method, you need to store it before replacing it, and call this method instead of object.

__new__.

For your simple case you could also write your subclass __init__ like this and assign the pointers from the Graph data structures to your subclass data. From networkx import Graph class MyGraph(Graph): def __init__(self, graph=None, **attr): if graph is not None: self. Graph = graph.

Graph # graph attributes self. Node = graph. Node # node attributes self.

Adj = graph. Adj # adjacency dict else: self. Graph = {} # empty graph attr dict self.

Node = {} # empty node attr dict self. Adj = {} # empty adjacency dict self. Edge = self.

Adj # alias self.graph. Update(attr) # update any command line attributes if __name__=='__main__': import networkx as nx R=nx. Gnp_random_graph(10,0.4) G=MyGraph(R) You could also use copy() or deepcopy() in the assignments but if you are doing that you might as well use G=MyGraph() G.

Add_nodes_from(R) G. Add_edges_from(R.edges()) to load your graph data.

You need to subclass each of the subclasses of nx. Graph that you wish to work with and add your required methods and attributes. Using mix-ins may make it easier to consistently extend the subclasses while obeying the DRY principle.

Though this example may seem straightforward enough, this method of hooking into a module is hard to generalize in a way that covers all the little problems that may crop up. I believe it's easier to just tailor it to the problem at hand. For instance, if the class you're hooking into defines its own custom __new__ method, you need to store it before replacing it, and call this method instead of object.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions