I'm a python addict !
Paul McGuire
ptmcg at austin.rr.com
Mon Jan 26 12:52:01 EST 2009
On Jan 26, 10:54 am, "J. Cliff Dyer" <j... at 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
More information about the Python-list
mailing list