Here you can use descriptors :
class deco(object): def __init__(self, func): self.func = func self.parent_obj = None def __get__(self, obj, type=None): self.parent_obj = obj return self def __call__(self, *args, **kwargs): return self.func(self.parent_obj, *args, **kwargs) def string(self, *args, **kwargs): return str(self(*args, **kwargs)) class Test(object): def __init__(self, value): self._value = value @deco def plus(self, n): return self._value + n
so that:
>>> test = Test(3) >>> test.plus(1) 4 >>> test.plus.string(1) '4'
This requires an explanation. deco is a decorator, but it is also a descriptor . A descriptor is an object that defines the alternative behavior that should be invoked when an object is considered as an attribute of its parent. Interestingly, border methods themselves are implemented using the descriptor protocol
This is a sip. Let's see what happens when we run the sample code. First, when we define the plus method, we use the deco decorator. Now we usually see decorator functions, and the return value of the function is the result of decorating. Here we use the class as a decorator. As a result, Test.plus not a function, but rather an instance of the deco type. This instance contains a link to the plus function that we want to wrap.
The deco class has a __call__ method, which allows instances to act as functions. This implementation simply passes the arguments to the plus function referenced. Note that the first argument will be a reference to the Test instance.
The tricky part is implementing test.plus.string(1) . To do this, we need a reference to the Test instance, the plus instance is an attribute. To do this, we use the descriptor protocol. That is, we define the __get__ method, which will be called whenever the deco instance gets access as an attribute of some instance of the parent class. When this happens, it stores the parent object within itself. Then we can simply implement plus.string as a method of the deco class and use the reference to the parent object stored in the deco instance to get the Test instance to which plus belongs.
This is a lot of magic, so here's a disclaimer: although it looks cool, it's probably not a good idea to implement something like this.