Welcome, guest | Sign In | My Account | Store | Cart

This code implements the policy design pattern in Python by using metaclasses and multiple inheritance.

Python, 50 lines
 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class PolicyClass(type):                      # All metaclasses inherit type.
    __dict = {}                               # Used to store created classes.
    def __new__(cls, name, bases, d):         # class, name, bases, dict
        def __make(*T):                       # Wrapper function for old class.
            try:                              #     T* = Bases of new class.
                this = cls.__dict[(name, T)]  # Make sure the class doesn't
            except KeyError:                  #     already exist.
                this = type(name,             # Construct new class using type.
                    tuple([C for C in         # type() only accepts tuples.
                    (bases + T)               # Add policies to original bases.
                    if C is not type]), d)    # Remove <type> from bases.
                cls.__dict[(name, T)] = this  # Store new class for later use.
            return this                       # Return resulting class.
        return __make                         # Replace original class.


# examples --

class Class(type):
    __metaclass__ = PolicyClass
    C = 'X'
    def __init__(self):                       # super(Class, self) won't work
        super(                                #     because Class has already
            self.__class__, self              #     been replaced with
        ).__init__()                          #     PolicyClass.__new__.__make.
        self.c = 'x'

class PolicyA(object):
    A = 'Y'
    def __init__(self):
        super(PolicyA, self).__init__()
        self.a = 'y'

class PolicyB(object):
    B = 'Z'
    def __init__(self):
        super(PolicyB, self).__init__()
        self.b = 'z'

ClassA = Class(PolicyA, PolicyB)
ClassB = Class(PolicyB, PolicyA)

assert ClassA is Class(PolicyA, PolicyB)      # PolicyClass.__dict allows this.
assert ClassA is not ClassB                   # These are NOT the same.

Instance = ClassA()

assert Instance.A.lower() == Instance.a       # Ensure original class works.
assert Instance.B.lower() == Instance.b       # Ensure inheritance works.
assert Instance.C.lower() == Instance.c       # Ensure MRO works.

I got the idea for this from this recipe: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/93378

Basically, by wrapping a class in a function, you can parameterize the class's base classes or types. (This is known as the policy design pattern.) However, the obvious flaw this method has is that it isn't polymorphic. Luckily though, Python's __metaclass__ functionality allows for such.

Of course, the usefulness of all this is very questionable, as making classes in Python is trivial enough as is.

1 comment

Yannick Loitiere 18 years ago  # | flag

C(T, U) is not C(U, T). Would sorting the argument list work ?

Created by Ian Bollinger on Mon, 10 Nov 2003 (PSF)
Python recipes (4591)
Ian Bollinger's recipes (2)

Required Modules

  • (none specified)

Other Information and Tasks