Method chaining
Rotwang
sg552 at hotmail.co.uk
Sat Nov 23 19:28:21 EST 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:
pass
def initr(self, obj):
super(type(self), self).__setattr__('__obj', obj)
def getr(self, name):
try:
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