On Jan 26, 10:54 am, "J. Cliff Dyer" <j...@sdf.lonestar.org> wrote: > On Fri, 2009-01-23 at 20:25 -0800, Paul McGuire wrote: > > Want to change the type/behavior of an object from class A to class > > B? How about this: > > > aobj = A() > > aobj.__class__ = B > > > Try *that* in as simple-looking C++ or Java! > > Wow. That looks very powerful and fun. But scary. Any thoughts on how > you would use that in a way that wouldn't unleash sulphurous code > smells? >
This technique is perfect for implementing the GoF State pattern. In the State pattern, you implement behavior for an object's various states using one of several interchangeable classes. The classes are "interchangeable" in that they all implement a common interface. Here is my favorite State pattern example, a traffic light: import time class TrafficLight(object): pass class RedLight(TrafficLight): cars_can_go = False pedestrians_can_cross = True color = (255,0,0) duration = 20 class YellowLight(TrafficLight): cars_can_go = True pedestrians_can_cross = False color = (255,255,0) duration = 5 class GreenLight(TrafficLight): cars_can_go = True pedestrians_can_cross = False color = (0,255,0) duration = 15 # now add in next_state class vars for state transitions RedLight.next_state = GreenLight YellowLight.next_state = RedLight GreenLight.next_state = YellowLight TrafficLight.initial_state = RedLight # run a traffic light for a while... can_they = lambda cond : ("can't","can")[cond] light = TrafficLight.initial_state() while 1: print light.__class__.__name__ print "waiting for", light.duration, "seconds" print "Cars", can_they(light.cars_can_go), "go" print "People", can_they(light.pedestrians_can_cross), "cross" print time.sleep(light.duration) # how you have to do it in C++ and Java # light = light.next_state() # using Python light.__class__ = light.next_state Gives this output: RedLight waiting for 20 seconds Cars can't go People can cross GreenLight waiting for 15 seconds Cars can go People can't cross YellowLight waiting for 5 seconds Cars can't go People can't cross RedLight waiting for 20 seconds Cars can't go People can cross ... and so on ... In Python, the base TrafficLight class isn't even necessary ("don't need no stinking interfaces!"), although it is a good place to define default behavior, and it helps tie together the other classes from a self-documentation standpoint. But any class that has the necessary attributes would suffice, whether it inherits from TrafficLight or not. class HoldForEmergencyVehiclesLight(object): cars_can_go = False pedestrians_can_cross = False color = (255,0,0) -- Paul -- http://mail.python.org/mailman/listinfo/python-list