Midas said:
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