joaquinn
joaquinn

Reputation: 175

Inherit from multiple classes and change the return type of all methods of one parent class

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

Answers (1)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

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

Related Questions