Method chaining

Rotwang sg552 at
Sun Nov 24 01:28:21 CET 2013

On 23/11/2013 19:53, Rotwang wrote:
> [...]
> That's pretty cool. However, I can imagine it would be nice for the
> chained object to still be an instance of its original type. How about
> something like this:
> [crap code]
> The above code isn't very good - it will only work on types whose
> constructor will copy an instance, and it discards the original. And its
> dir() is useless. Can anyone suggest something better?

Here's another attempt:

class dummy:

def initr(self, obj):
     super(type(self), self).__setattr__('__obj', obj)
def getr(self, name):
         return super(type(self), self).__getattribute__(name)
     except AttributeError:
         return getattr(self.__obj, name)
def methr(method):
     def selfie(self, *args, **kwargs):
         result = method(self.__obj, *args, **kwargs)
         return self if result is None else result
     return selfie

class chained(type):
     typedict = {}
     def __new__(cls, obj):
         if type(obj) not in cls.typedict:
             dict = {}
             for t in reversed(type(obj).__mro__):
                 dict.update({k: methr(v) for k, v in t.__dict__.items()
                             if callable(v) and k != '__new__'})
             dict.update({'__init__': initr, '__getattribute__': getr})
             cls.typedict[type(obj)] = type.__new__(cls, 'chained%s'
                 % type(obj).__name__, (dummy, type(obj)), dict)
         return cls.typedict[type(obj)](obj)

This solves some of the problems in my earlier effort. It keeps a copy 
of the original object, while leaving its interface pretty much 
unchanged; e.g. repr does what it's supposed to, and getting or setting 
an attribute of the chained object gets or sets the corresponding 
attribute of the original. It won't work on classes with properties, 
though, nor on classes with callable attributes that aren't methods (for 
example, a class with an attribute which is another class).

More information about the Python-list mailing list