ObjectA calling ObjectB
Peter Otten
__peter__ at web.de
Sun Dec 28 09:13:45 EST 2003
Midas wrote:
> Thanks for assisting.
>
> What I'm trying to do is as follows:
>
> Part 1) Create 10 new assorted objects
> Part 2) Link up the objects, somehow, so they can communicate with each
> other directly, like parts of an electrical circuit.
> Part 3) Call the first object, which calls another, etc. like an
> electrical circuit.
>
> To change the circuit, I would only change part 2 and perhaps part 3.
>
> For example, ObjectX could have an input, for a string, and two outputs.
> If the input is "TurnOnS", it calls ObjectY.Input3
> If the input is "TurnOnT", it calls ObjectZ.Input7
>
> ObjectX would call either, ObjectY.Input3 or ObjectZ.Input7, because it
> was connected that way in part 2.
>
> I could then later change part 2 so ObjectX called either ObjectE.Input2
> or ObjectF.Input9 In other words, I could "re-wire" the circuit without
> changing anything in the objects.
I think what you want is the observer pattern that is widely used, e. g. for
wiring the Java Swing GUI with the underlying data model.
Below is a toy example that connects some logical components. Rather than
invoking different methods on a per class basis, I store object references
directly and introduce a common interface for all classes, i. e. the
notify() method. As always in Python, the common base class is not a
necessity to make the compiler happy, but a means to reduce redundant code.
<demo.py>
class Gadget(object):
def __init__(self, name=None):
self._state = False
self.outputs = []
self.inputs = []
self.name = name
def addinputs(self, *inputs):
for i in inputs:
self.addinput(i)
def addoutput(self, o):
self.outputs.append(o)
o.inputs.append(self)
def addinput(self, i):
self.inputs.append(i)
i.outputs.append(self)
def addoutputs(self, *outputs):
for o in outputs:
self.addoutput(o)
def setstate(self, state):
if self._state != state:
self._state = state
self.changed()
def getstate(self):
return self._state
state = property(getstate, setstate)
def changed(self):
for o in self.outputs:
o.notify(self)
class Not(Gadget):
def notify(self, sender):
self.state = not sender.state
class And(Gadget):
def notify(self, sender):
for i in self.inputs:
if not i.state:
self.state = False
break
else:
self.state = True
class Or(Gadget):
def notify(self, sender):
for i in self.inputs:
if i.state:
self.state = True
break
else:
self.state = False
class Input(Gadget):
def __str__(self):
return "\t%s is now %s" % (self.name, {False: "Off", True:
"On"}[self.state])
class Output(Input):
def changed(self):
print str(self)
def notify(self, sender):
self.state = sender.state
if __name__ == "__main__":
def state(v):
if v: return True
else: return False
def printState():
for g in ("Input:", ione, itwo, ithree, "Output:", red, green,
blue):
print g
one, two, three = False, False, False
# define the model
ione, itwo, ithree = [Input(name) for name in "one two three".split()]
gnot = Not()
gor = Or()
gand = And()
gnot.addinputs(ione)
gand.addinputs(gnot, itwo)
gor.addinputs(ione, itwo, ithree)
red, green, blue = [Output(name) for name in "red green blue".split()]
gor.addoutput(red) # one or two or three
gand.addoutput(green) # two and (not one)
gnot.addoutput(blue) # not one
#play with it
print "set one, two, three to True or False, e. g."
print "one=True"
print "type '?' to print the current state, 'quit' to quit"
while True:
cmd = raw_input()
if cmd == "quit":
break
elif cmd in ("?", "print"):
printState()
else:
try:
exec cmd
except:
pass
else:
ione.state = state(one)
itwo.state = state(two)
ithree.state = state(three)
</demo.py>
And now a sample session (note that I didn't bother to ensure a consistent
initial state):
<session>
set one, two, three to True or False, e. g.
one=True
type '?' to print the current state, 'quit' to quit
?
Input:
one is now Off
two is now Off
three is now Off
Output:
red is now Off
green is now Off
blue is now Off
one=1
red is now On
two=1
three=1
one=two=three=0
green is now On
blue is now On
green is now Off
red is now Off
two=1
green is now On
red is now On
quit
</session>
Peter
More information about the Python-list
mailing list