Skip to content

Instantly share code, notes, and snippets.

@cosmin
Created March 12, 2009 00:59
Show Gist options
  • Save cosmin/77848 to your computer and use it in GitHub Desktop.
Save cosmin/77848 to your computer and use it in GitHub Desktop.
# 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