In order to add a level of hierarchy, curves
needs to be an actual object, yes. There is no difference between foo.curves.plot()
and the following:
c = foo.curves
c.plot()
So foo.curves
needs to be an object that has a plot
method.
Also, since the method is called on the curves
object, the method will be bound to that object. So unless you set it up that way, the curves
object will not have access to your actual class.
You could pass the instance in the curves
constructor though:
class Curves (object):
def __init__ (self, parent):
self.parent = parent
def plot (self):
self.parent._plot()
class MyClass (object):
def __init__ (self):
self.curves = Curves(self)
def _plot (self):
print('Actual plot implementation')
Then you can use it as foo.curves.plot()
:
>>> foo = MyClass()
>>> foo.curves.plot()
Actual plot implementation
You could also automate this a bit by using a descriptor for curves
. For example, this is a possible solution:
class Accessor (object):
def __init__ (self, prefix = ''):
self.prefix = prefix
def __get__ (self, instance, owner):
return AccessorDelegate(instance, self.prefix)
class AccessorDelegate (object):
def __init__ (self, instance, prefix):
self.instance = instance
self.prefix = prefix
def __getattr__ (self, name):
return getattr(self.instance, self.prefix + name)
The benefit is obviously that you only need to define those a single time and then they’ll work for all your classes. You would use it like this in your class:
class MyClass (object):
curves = Accessor('_curves_')
def _curves_plot(self):
print('Implementation of curves.plot')
Used exactly as above:
>>> foo = MyClass()
>>> foo.curves.plot()
Implementation of curves.plot