Software Design Spring 2007 For Wednesday you should have: 1) finished Homework 5 2) read Chapter 14 For next time: 1) read Chapter 15 2) work on Homework 6 Quiz on Monday, also Ben will be available for hw6 help. Exam 1 Solutions ---------------- Total points = 46, median score = 34 40-46 12 Here is the distribution of scores. 35-39 5 Not bad overall, but I think the exam was 30-34 5 a little too hard for where we are. 25-29 9 That's ok -- think of it as a learning 20-24 2 exam more than an evaluative exam. 15-19 3 The debugging section hurt some people. Page 1: break statement, continue statement, keys, values, equivalent (equal got 1/2 credit because it is ambiguous), call, invoke, aliasing, immutable, abstraction. Page 2: def nturtles(ts): n = len(ts) res = [] for i in range(n-1): for j in range(i+1, n): t1, t2 = ts[i], ts[j] g = gforce(t1, t2) tup = g, t1, t2 res.append(tup) return res 1) don't write gforce, or worry about how it works. 2) save the result from gforce: g = gforce(...) 3) return the list of tuples, don't print anything 4) use append or res +=, but not res[i] unless you have allocated space 5) use "is" to check for identical turtles, not == Page 3: Here's a solution (with implementation). def polypies(t, ns, r): """use turtle (t) to draw a row of polypies with some space between. (ns) is a list of integers specifying the number of sides in each pie. (r) is the spoke length of all pies. (t) ends at the starting position and orientation. """ for i in ns: polypie(bob, i, 40) bob.pu() bob.fd(r*2 + 10) bob.pd() def polypie(t, n, r): """use turtle (t) to draw a pie with (n) triangular slices with spoke length (r). (n) must be greater than 2. (t) ends at the starting position, orientation. """ theta = 360.0 / n for i in range(n): icosoles(t, r, theta/2) t.lt(theta) def icosoles(t, r, theta): """use turtle (t) to draw an equilateral triangle with leg length (r) and peak angle (theta) in degrees. (t) starts and ends at the peak, facing the middle of the base. """ y = r * sin(theta*pi/180) t.rt(theta) t.fd(r) t.lt(90+theta) t.fd(2*y) t.lt(90+theta) t.fd(r) t.lt(180-theta) 1) use turtle position and heading, don't pass as parameters 2) don't forget to pass the turtle 3) choose good names! 4) explain what the function does, not how 5) good division of labor means the helper functions should do some of the hard work. 6) don't forget preconditions, for example, n>2 7) don't forget postconditions, for example, final turtle position 8) appropriate generalization: triangle is probably too general (requires more parameters than icosoles) 9) need to know basis: triangle function shouldn't have to know about the pie. However 1) interface design is hard -- most beginners don't do it at all. 2) it is very hard to get right on the first try -- evolves with incremental development. 3) what I looked for on the exam was a good first draft. Page 4: I didn't make a big deal about semantic vs. run-time error. Strictly speaking, if an erroneous line of code would run without producing an error message, it's a semantic error, even if it would lead to a run-time error later or somewhere else. But it doesn't matter. def process_word(word, d): word.lower() # word = word.lower() # semantic error if word in d: d[word] += 1 else: d[word] = 1 def process_line(line, d): t = line.split() for i in len(t): # range(len(t)) process_word(t[i], d) # run-time error def process_file(filename): d = {} fp = open(filename, 'r') for line in fp: process_line(line, 'd') # no quotes on variable name return d # semantic error def print_top_ten(d): t = [] for k, v in d.iteritems() # need a colon: (syntax) pair = v, k t = t.append(pair) # append returns None # semantic error t.sort(reverse=True) for v, k in t[0:10]: print k d = process_file('gatsby.txt') print_top_ten(d) Classes ------- Big dose of new vocabulary: class, instance, instantiate, object, constructor, attribute LEARN IT, SPEAK IT, MAKE IT A PART OF YOU. A class is a user-defined type. class Point: pass # later there will be method definitions here class Rectangle: pass Creating a class defines a function* with the same name: blank = Point() schmectangle = Rectangle() These functions are called constructors. Invoking a constuctor creates an instance of the class. An instance is a member of a class. An object is something that can be referred to. A reference to an object can be assigned to a variable, passed as an argument or returned as a return value. In Python: All instances are objects (can be referred to...) AND all objects are instances (belong to some class). In casual speech, object and instance are used interchangeably. Attributes ---------- Objects have attributes (emphasis on the first syllable) An attribute is like a variable that belongs to an object. Try this: from World import * world = TurtleWorld() bob = Turtle(world) print bob.x, bob.y print bob.color bob.color = 'blue' print bob.color What color is bob? You can add a new attribute to an object at any time! bob.new_feature = 'whatever you want' print bob.new_feature UML object diagrams ------------------- Download http://wb/sd/code/rectangle_lumpy.py Draw a stack diagram, then run it to see if you're right. import Lumpy lumpy = Lumpy.Lumpy() lumpy.make_reference() class Rectangle: pass class Point: pass def find_center(box): corner = box.corner p = Point() p.x = box.corner.x + box.width/2 p.y = box.corner.y + box.height/2 lumpy.object_diagram() return p box = Rectangle() box.width = 100 box.height = 200 box.corner = Point() box.corner.x = 10 box.corner.y = 20 center = find_center(box)