Reputation: 954
I have a class with a lot of methods which are logically can be grouped. I would like to group them like in pandas
. For example, in pandas all plotting method are accessible by df.plot
i.e. df.plot.hist(...)
, df.plot.bar(...)
. Rolling methods also grouped and accessible like df.rolling(2).sum()
.
I looked at the source code of pandas
but it did not help.
How can I implement such intermediate accessor classes like .plot.<plot method>
, .normalize.<normalize method>
, .smooth.<smooth method>
, etc. for my custom class?
Upvotes: 0
Views: 163
Reputation: 44878
Here's a very basic implementation:
>>> class FancyPlotting:
... def __init__(self, info: dict):
... self.info = info
... def plot(self, *args):
... ... # use `self.info` and `args` to decide what and how to plot
...
>>> class FancyDataframe:
... def __init__(self, data: list):
... self.data = data
... def rolling(self, number: int):
... return FancyRoller(self.data, number)
... @property
... def plot(self):
... return FancyPlotting({'points': self.data})
...
>>> class FancyRoller:
... def __init__(self, data: list, window_length: int):
... self.data, self.window_length = data, window_length
... def sum(self):
... return sum(self.data[::self.window_length]) # this is not an actual implementation
...
>>> df = FancyDataframe([1,2,3,4,5,6,7,8])
>>> df.plot.plot()
# does stuff
>>> df.rolling(1).sum()
36
Of course, reading pandas' source should give you a better idea of how this is done.
EDIT: Python won't unnecessarily copy data, so excessive memory usage is not a problem:
class FancyRoller:
def __init__(self, data: list, **settings):
self.data, self.settings = data, settings
def sum(self):
return sum(self.data[::self.settings['size']])
class FancyDataframe:
def __init__(self, data):
self.data = data
def rolling(self, size):
# again, this is just an example
return FancyRoller(self.data, size=size)
df = FancyDataframe([1,2,3,4,5,6,7])
assert id(df.data) == id(df.rolling(2).data)
print(df.rolling(1).sum())
Upvotes: 2