- Vocabulary
You need to understand these terms, and in the case of specific methods, you need to know how and why to implement them.
- struct, class, object, instance, type, isinstance
- attribute, method, constructor, __dict__
- __init__, __str__, __repr__, __eq__, __hash__
Note that this is a subset of material from previous semesters.
In particular, while you may wish to review those materials
here,
you do not need to know the following:
- subclass, superclass, super, inherit, override
- static method, @staticmethod, class method, @classmethod
- __ne__, __add__, __radd__, __gt__, __ge__, __lt__, __le__, etc..
- Structs
(download structClass.py)
######################################################
# Structs (save in structClass.py (do not save in struct.py!))
######################################################
# Here we use 'struct' in the classic sense:
# http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29
# Note that this is not the same as Python's struct module:
# https://docs.python.org/2/library/struct.html
class Struct(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
d = self.__dict__
results = [type(self).__name__ + "("] # or: self.__class__.__name__
for key in sorted(d.keys()):
if (len(results) > 1): results.append(", ")
results.append(key + "=" + repr(d[key]))
results.append(")")
return "".join(results)
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __hash__(self):
return hash(repr(self)) # inefficient but simple
def testStructClass():
print "Testing Struct class...",
obj = Struct()
obj.x = 42
assert(obj.x == 42)
obj = Struct(x=2, b=True, s="abc")
assert((obj.x == 2) and (obj.b == True) and (obj.s == 'abc'))
obj.x = 3
assert(obj.x == 3)
assert(str(obj) == "Struct(b=True, s='abc', x=3)") # alphabetical keys
assert(str([obj]) == "[Struct(b=True, s='abc', x=3)]")
obj2 = eval(repr(obj))
assert(obj == obj2)
assert(obj is not obj2) # they are equal, but not aliases
s = set()
assert(obj not in s)
s.add(obj)
assert(obj in s)
assert(obj2 in s) # since (obj == obj2)
obj.x += 1 # obj is mutable, which is bad, because...
assert(obj not in s) # sigh...
class Person(Struct): pass
joe = Person(name="Joe", age=42)
assert(str(joe) == "Person(age=42, name='Joe')")
assert(type(joe) == Person)
assert(isinstance(joe, Person) == True)
assert(isinstance(joe, Struct) == True)
print "Passed!"
if __name__ == "__main__":
testStructClass()
- Example: dotsDemo
######################################################
# Struct Example: dotsDemo
######################################################
import eventBasedAnimation
import random
from structClass import Struct # defined above (saved in structClass.py)
class Dot(Struct): pass
def dotsDemoInitFn(data):
data.dots = [ ]
data.aboutText = data.windowTitle = "dotsDemo (click inside/outside dots)"
def dotContainsPoint(dot, x, y):
d = ((dot.x - x)**2 + (dot.y - y)**2)**0.5
return (d <= dot.r)
def dotsDemoMouseFn(event, data):
for dot in reversed(data.dots):
if (dotContainsPoint(dot, event.x, event.y)):
dot.clickCount += 1
return
radius = random.randint(20,50)
color = random.choice(["pink","orange","yellow","green","cyan","purple"])
data.dots.append(Dot(x=event.x, y=event.y, r=radius,
fill=color, clickCount=0))
def dotsDemoDrawFn(canvas, data):
for dot in data.dots:
canvas.create_oval(dot.x-dot.r, dot.y-dot.r,
dot.x+dot.r, dot.y+dot.r,
fill=dot.fill)
canvas.create_text(dot.x, dot.y, text=str(dot.clickCount))
eventBasedAnimation.run(
initFn=dotsDemoInitFn,
mouseFn=dotsDemoMouseFn,
drawFn=dotsDemoDrawFn,
)
- Example: betterDotsDemo (with methods, without Structs)
######################################################
# betterDotsDemo (with methods, without Structs)
######################################################
import eventBasedAnimation
import random
class Dot(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.r = random.randint(20,50)
self.fill = random.choice(["pink","orange","yellow","green",
"cyan","purple"])
self.clickCount = 0
def containsPoint(self, x, y):
d = ((self.x - x)**2 + (self.y - y)**2)**0.5
return (d <= self.r)
def draw(self, canvas):
canvas.create_oval(self.x-self.r, self.y-self.r,
self.x+self.r, self.y+self.r,
fill=self.fill)
canvas.create_text(self.x, self.y, text=str(self.clickCount))
def betterDotsDemoInitFn(data):
data.dots = [ ]
data.aboutText = data.windowTitle = "betterDotsDemo (click in/outside dots)"
def betterDotsDemoMouseFn(event, data):
for dot in reversed(data.dots):
if (dot.containsPoint(event.x, event.y)):
dot.clickCount += 1
return
data.dots.append(Dot(event.x, event.y))
def betterDotsDemoDrawFn(canvas, data):
for dot in data.dots:
dot.draw(canvas)
eventBasedAnimation.run(
initFn=betterDotsDemoInitFn,
mouseFn=betterDotsDemoMouseFn,
drawFn=betterDotsDemoDrawFn,
)
- Example: bestDotsDemo (with Animation class)
Requires
eventBasedAnimation.py (version 1.10 or later)
######################################################
# bestDotsDemo (with Animation class)
######################################################
import eventBasedAnimation # requires version 1.10 or later
import random
class Dot(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.r = random.randint(20,50)
self.fill = random.choice(["pink","orange","yellow","green",
"cyan","purple"])
self.clickCount = 0
def containsPoint(self, x, y):
d = ((self.x - x)**2 + (self.y - y)**2)**0.5
return (d <= self.r)
def draw(self, canvas):
canvas.create_oval(self.x-self.r, self.y-self.r,
self.x+self.r, self.y+self.r,
fill=self.fill)
canvas.create_text(self.x, self.y, text=str(self.clickCount))
class BestDotsDemo(eventBasedAnimation.Animation):
def onInit(self):
self.dots = [ ]
self.aboutText = self.windowTitle = "bestDotsDemo (click in/out dots)"
def onMouse(self, event):
for dot in reversed(self.dots):
if (dot.containsPoint(event.x, event.y)):
dot.clickCount += 1
return
self.dots.append(Dot(event.x, event.y))
def onDraw(self, canvas):
for dot in self.dots:
dot.draw(canvas)
BestDotsDemo().run()
- Example: smileyClassDemo
Requires
eventBasedAnimation.py (version 1.10 or later)
######################################################
# smileyClassDemo (similar to bestDotsDemo, but a bit more fun)
######################################################
import eventBasedAnimation # requires version 1.10 or later
import random
#from Tkinter import *
class Smiley(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.r = random.randint(50,100)
self.color = random.choice(["cyan", "yellow", "lightGreen", "pink",
"orange", "green", "lightBlue", "purple"])
self.maxSmileyPoints = 100
self.smileyPoints = self.maxSmileyPoints # the more points the happier
def draw(self, canvas):
(x, y, r) = (self.x, self.y, self.r)
# face
canvas.create_oval(x-r, y-r, x+r, y+r,
fill=self.color, outline="black", width=4)
# eyes
eyeY = y-r/3
eyeR = r/6
for eyeX in [x-r/3, x+r/3]:
canvas.create_oval(eyeX-eyeR, eyeY-eyeR, eyeX+eyeR, eyeY+eyeR,
fill="black")
# mouth
mouthY1 = y+r/3
mouthDy = r/6 # max height of mouth smile
halfMax = self.maxSmileyPoints/2
mouthY0 = mouthY1 - mouthDy*(self.smileyPoints - halfMax)/halfMax
mouthY2 = mouthY0
mouthDx = r*2/3
for mouthX0 in [x-mouthDx, x+mouthDx]:
canvas.create_line(mouthX0, mouthY0, x, mouthY1,
fill="black", width=4)
def contains(self, x, y):
return ((self.x - x)**2 + (self.y - y)**2 <= self.r**2)
class SmileyClassAnimationDemo(eventBasedAnimation.Animation):
def onMouse(self, event):
for smiley in reversed(self.smileys):
if (smiley.contains(event.x, event.y)):
smiley.smileyPoints = smiley.maxSmileyPoints
return
# clicked outside of all smileys, so make a new smiley
newSmiley = Smiley(event.x, event.y)
self.smileys.append(newSmiley)
def onStep(self):
for smiley in self.smileys:
if (smiley.smileyPoints > 0):
smiley.smileyPoints -= 1
def onInit(self):
self.timerDelay = 100
self.smileys = [ ]
def drawSmileys(self, canvas):
for smiley in self.smileys:
smiley.draw(canvas)
def drawText(self, canvas):
texts = [self.smileyMessage,
"Click in Smileys to make them Smile!",
"Click outside Smileys to make a new Smiley!"
]
font = "Arial 20 bold"
x = self.width/2
for i in xrange(len(texts)):
y = 25*(i+1)
canvas.create_text(x, y, text=texts[i], font=font)
def onDraw(self, canvas):
self.drawSmileys(canvas)
self.drawText(canvas)
SmileyClassAnimationDemo(smileyMessage="Smile!", width=800, height=600).run()