Reputation: 175
I want to create a new class that inherits from two parent classes, for example my own object class and pandas DataFrame class. Now I want to overwrite the to_excel() method of pandas DataFrame to add some optical stuff.
class myObject(object):
# some stuff
pass
class myDataFrame(pandas.DataFrame, myObject):
def to_excel(self, *args, **kwargs):
super(myDataFrame, self).to_excel(*args, **kwargs)
# some additional things
return
The problem is: if an instance of myDataFrame is created, but an operation like the following is done:
a = myDataFrame(data=[1,2,3], index=["a", "b", "c"], columns=["Values"])
a = a.set_index("Values", drop=False)
Then set_index() will return an object of type pandas.DataFrame, not of type myDataFrame (of course I could use set_index(inplace=True), but thats not what I want). Using to_excel() now will, of course, not call my own method but pandas original method.
In other words, I want objects that are instances of myDataFrame to never change their type. The class myDataFrame should somehow overwrite all methods of pandas.DataFrame and change their returned type to myDataFrame, if nescessary. Doing this hard-coded by overwriting all methods by hand feels unpythonic to me.
What could be the smartest way to do this? I know of meta classes and decorators but somehow dont really understand how I have to handle them to achieve the goal. I also dont want to touch anything within the pandas module.
Thanks for hints!
Upvotes: 1
Views: 234
Reputation: 160637
See the Sub-classing pandas Data Structures section override constructor properties.
In short, also define a _constructor
property that returns your subclass:
@property
def _constructor(self):
return type(self)
This specific property is responsible for:
_constructor
: Used when a manipulation result has the same dimensions as the original.
Additional constructors: _constructor_sliced
and _constructor_expanddim
can be defined when an operation on the sub-classed structure results in it's dimensions getting changed.
Upvotes: 2