Diez B. Roggisch wrote: > George Sakkis schrieb: >> I have a situation where one class can be customized with several >> orthogonal options. Currently this is implemented with (multiple) >> inheritance but this leads to combinatorial explosion of subclasses as >> more orthogonal features are added. Naturally, the decorator pattern >> [1] comes to mind (not to be confused with the the Python meaning of >> the term "decorator"). >> >> However, there is a twist. In the standard decorator pattern, the >> decorator accepts the object to be decorated and adds extra >> functionality or modifies the object's behavior by overriding one or >> more methods. It does not affect how the object is created, it takes >> it as is. My multiple inheritance classes though play a double role: >> not only they override one or more regular methods, but they may >> override __init__ as well. Here's a toy example: >> >> class Joinable(object): >> def __init__(self, words): >> self.__words = list(words) >> def join(self, delim=','): >> return delim.join(self.__words) >> >> class Sorted(Joinable): >> def __init__(self, words): >> super(Sorted,self).__init__(sorted(words)) >> def join(self, delim=','): >> return '[Sorted] %s' % super(Sorted,self).join(delim) >> >> class Reversed(Joinable): >> def __init__(self, words): >> super(Reversed,self).__init__(reversed(words)) >> def join(self, delim=','): >> return '[Reversed] %s' % super(Reversed,self).join(delim) >> >> class SortedReversed(Sorted, Reversed): >> pass >> >> class ReversedSorted(Reversed, Sorted): >> pass >> >> if __name__ == '__main__': >> words = 'this is a test'.split() >> print SortedReversed(words).join() >> print ReversedSorted(words).join() >> >> >> So I'm wondering, is the decorator pattern applicable here ? If yes, >> how ? If not, is there another way to convert inheritance to >> delegation ? > > Factory - and dynamic subclassing, as shown here: > > import random > > class A(object): > pass > > class B(object): > pass > > > def create_instance(): > superclasses = tuple(random.sample([A, B], random.randint(1, 2))) > class BaseCombiner(type): > > def __new__(mcs, name, bases, d): > bases = superclasses + bases > return type(name, bases, d) > > class Foo(object): > __metaclass__ = BaseCombiner > return Foo() > > for _ in xrange(10): > f = create_instance() > print f.__class__.__bases__
Right now I see of course that I could have spared myself the whole __metaclass__-business and directly used type()... Oh well, but at least it worked :) Diez -- http://mail.python.org/mailman/listinfo/python-list