A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from http://code.activestate.com/recipes/577658-composition-of-classes-instead-of-multiple-inherit below:

Composition of classes instead of multiple inheritance « Python recipes « ActiveState Code

MI can be difficult and confusing, and if the base classes don't cooperate -- well, cooperative MI won't work.

One way around this is to use composition instead. This class decorator will combine the source classes with the target class, ensuring that no duplications occur (raises a TypeError if there are any).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import new

class Compose(object):
    def __init__(self, *parts):
        self.parts = parts
    def __call__(self, cls):
        conflicts = dict()
        parts = self.parts + (cls,)
        for i, part1 in enumerate(parts):
            for partn in parts[i+1:]:
                for attr in dir(part1):
                    if attr[:2] == attr[-2:] == '__':
                        continue
                    if getattr(partn, attr, None):
                        if attr not in conflicts:
                            conflicts[attr] = [part1]
                        conflicts[attr].append(partn)
        if conflicts:
            text = []
            for key, lst in conflicts.items():
                text.append('    %s:' % key)
                for c in lst:
                    text.append('        %s' % c)
            text = '\n'.join(text)
            raise TypeError("Conflicts while composing:\n%s" % text)
        for part in self.parts:
            for attr in dir(part):
                if attr[:2] == attr[-2:] == '__':
                    continue
                thing = getattr(part, attr)
                thing = getattr(thing, '__func__', None) or thing
                if callable(thing):
                    setattr(cls, attr, new.instancemethod(thing, None, cls))
                else:
                    setattr(cls, attr, thing)
        return cls

Brief example:

import unittest from compose import Compose

class Eggs(object): def test_eggs_01(self): print('testing eggs_01') def test_eggs_02(self): print('testing eggs_02')

class Spam(object): def test_spam_01(self): print('testing spam_01') def test_spam_02(self): print('testing spam_02')

@Compose(Spam, Eggs) class TestAll(unittest.TestCase): def setUp(self): print('Setting up...') def tearDown(self): print('Tearing down...') def test_something(self): print('testing something')

if __name__ == '__main__': unittest.main()


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4