I have a class like this: class MySeq(): def __init__(self, *seq, c=12): self.__c = c self.__pc = sorted(set([i % __c for i in seq])) self.order = ([[self.__pc.index(i % __c), i // __c] for i in seq]) #other calculated attributes
@property def pitches(self): return [self.__pc[i[0]] + i[1] * self.__c for i in self.order] #other methods The "pitches" attribute initially reconstructs the "seq" arguments but can be modified by writing to the "order" attribute. The "pitches" attribute represents the instances and as such I found myself adding a lot of methods like: def __getitem__(self, index): return self.pitches[index] def __len__(self): return len(self.pitches) def __iter__(self): return iter(self.pitches) def __repr__(self): return str(self.pitches) and so on, and calling a lot of list methods on the "pitches" attribute of MySeq instances elsewhere. I thought of making MySeq a subclass of list with "pitches" as its contents, but then I would have had to override a lot of methods case-by-case, for example to ensure that any alterations to "pitches" were reflected in the other calculated attributes. So I wrote this function which takes a method, modifies it to apply to an instance attribute, and takes care of any quirks: def listmeth_to_attribute(meth, attr): def new_meth(inst, *args): #ensure comparison operators work: args = [getattr(i, attr) if isinstance(i, inst.__class__) else i for i in args] reference = getattr(inst, attr) test = reference[:] result = meth(test, *args) #ensure instance is reinitialised #if attribute has been changed: if test != reference: inst.__init__(*test) #ensure slices are of same class if isinstance(result, meth.__objclass__): result = inst.__class__(*result) return result return new_meth and this decorator to apply this function to all the list methods and add them to MySeq: def add_mod_methods(source_cls, modfunc, modfunc_args, *overrides): """Overides = any methods in target to override from source""" def decorator(target_cls): for name, meth in vars(source_cls).items(): if name not in dir(target_cls) or name in overrides: setattr(target_cls, name, modfunc(meth, *modfunc_args)) return target_cls return decorator a kind of DIY single inheritance, used like this: @add_mod_methods(list, listmeth_to_attribute, ('pitches',), '__repr__') class MySeq(): ..... Now I can call list methods transparently on MySeq instances, like subclassing but without all the overriding. If this works it will simplify a lot of code in my project. But the fact that I haven't seen this approach before increases the likelihood it may not be a good idea. I can almost hear the screams of "No, don't do that!" or the sound of me slapping my forehead when someone says "Why don't you just...". So before I put it in, I'd appreciate any comments, warnings, criticisms, alternatives etc.. Regards, John -- http://mail.python.org/mailman/listinfo/python-list