Created
March 12, 2009 00:59
-
-
Save cosmin/77848 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# An example of separating behavior from data in Python | |
import copy, new | |
### Class helpers | |
def create_class(__bases__=(object, ), **kw): | |
return new.classobj('FakeClass', __bases__, kw) | |
def combine(*classes): | |
""" Create class hierarchies programatically """ | |
return new.classobj('CombinedClass', classes, {}) | |
def add_methods(obj, **methods): | |
""" Add methods to a class """ | |
for k, v in methods.items(): | |
setattr(obj.__class__, k, v) | |
def steal_methods(cls, *method_names): | |
return dict((m, getattr(cls, m).im_func) for m in method_names) | |
### Instance helpers | |
class Generic(object): | |
""" A generic class with no functionality, instances have private copies | |
of __class__ so behavior can be added to them programatically | |
""" | |
def __init__(self, **kw): | |
self.__dict__ = dict(kw) | |
self.__class__ = new.classobj('GenericInstance', (Generic,), {}) | |
def add_behavior(obj, *classes): | |
""" Adds each of the given classes to the bases for this object's class | |
Therefore inheriting any methods those classes define | |
""" | |
obj.__class__.__bases__ = tuple(obj.__class__.__bases__ + classes) | |
### Time for a little test | |
# let's create two behavior classes | |
Adder = create_class(sum=lambda self: self.x + self.y) | |
Multiplier = create_class(mul=lambda self: self.x * self.y) | |
a1 = Generic(x=2, y=3) | |
# let's add a new method directly to a1 | |
add_methods(a1, sum=lambda self: self.x + self.y) | |
print 'a1.sum() = ', a1.sum() | |
a2 = Generic(x=3, y=5) | |
# let's add behaviors to a2 | |
add_behavior(a2, Adder, Multiplier) | |
print '' | |
print 'a2.sum() = ', a2.sum() | |
print 'a2.mul() = ', a2.mul() | |
a3 = Generic(x=5, y=7) | |
# let's steal some methods from the combination of Adder and Multiplier | |
# and add them to a3 | |
add_methods(a3, **steal_methods(combine(Adder, Multiplier), | |
'sum', 'mul')) | |
print '' | |
print 'a3.sum() = ', a3.sum() | |
print 'a3.mul() = ', a3.mul() | |
#### Expected output of running the program | |
# a1.sum() = 5 | |
# | |
# a2.sum() = 8 | |
# a2.mul() = 15 | |
# | |
# a3.sum() = 12 | |
# a3.mul() = 35 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment