Table of Contents
- Introduction
- What's special about Python?
- Structure of quizzes and programs in CS 9H
- Group A
- Group B
- Group C
- Group D
- Group E
Study guides. Each study guide focuses on a particular programming topic. It provides references to textbook material describing the topic, and suggests exercises for self-study. The study guides reference the following text, available online.
How to Think Like a Computer Scientist: Learning with Python, by Allen Downey, Jeff Elkner and Chris Meyers (Green Tea Press, 2004; ISBN 0971677506). You will be able to access it online.In addition, there are a supplementary set of online notes which are listed (and linked) in the reading sections below.
Programming assignments. Each one has a header page (this tells you the title and related topics) that is followed by the actual assignment.
System information. Some programming assignments require you to use features of Python not adequately described in the standard documents. More information is included with the corresponding study guide.
Sample quiz questions, with solutions. These help you prepare for the quizzes.
The following table outlines the relationship between quizzes and programs. All the material for a particular grouping must be completed before material in the next grouping; however, quizzes and programs within a group may be done in any order.
For information about deadlines, consult the Information and Regulations document.
In this activity, you familiarize yourself with software to compute deadline penalties in the self-paced courses and supply us with some administrative information that makes it easier to contact you.
You learn the "art" of using Python not only by writing programs of your own, but also by reading those of others. Quiz questions ask you to generate code as well as understand, debug, and criticize already-written code. There is a lot of reading for this first topic, so get started right away. It will cover most of the Python syntax you will learn:
-2 ** 3 + 7 -3 % 5 - 8 'spam' * 3 + 'lovely spam' 'spam' + 3 + 'lovely spam' 'eggs' and '' and 5 0 or 4 and 2 or 7
Answers:
>>> -2 ** 3 + 7 -1 >>> -3 % 5 - 8 -6 >>> 'spam' * 3 + 'lovely spam' 'spamspamspamlovely spam' >>> 'spam' + 3 + 'lovely spam' TypeError: cannot concatenate 'str' and 'int' objects >>> 'eggs' and '' and 5 '' >>> 0 or 4 and 2 or 7 2
>>> mystery(15, 'red') 'redredredredred' >>> mystery(12, 'green') 'greengreengr' >>> mystery(26, 'aquamarine') 'aquamarineaquamarineaquama'
Answer with looping:
def mystery(n, word): result = '' while len(result) < n: result += word return result[:n]
Answer without looping:
def mystery(n, word): return (word*n)[:n]
def make-scaler(c)
def scale(n)
return c * n
return('scale')
Answer with errors removed (but indicated in comments)
def make_scaler(c): # 2 errors: '-' not allowed in names & missing ':' def scale(n): # 1 error : missing ':' return c * n # 0 errors return(scale) # 2 errors: the indent was not consistent & no quotes
Answer with lambda
def make_scaler(c): return lambda n: c * n
Creating add1
>>> double = make_scaler(2) >>> double(3) 6
This program introduces you to Python by giving you practice with the interpreter, expressions, strings, functions and the various flow-of-control constructs.
In this group, you will learn about Python's various techniques for maintaining collections of data and handling mutation. Again, there's a lot of reading, but by the end of this section, you will have significant Python fluency. You'll learn:
a = [1, 2] b = [1, 2] c = [6, 7, a] d = [6, 7, a] e = a + c f = [c, d] a.append(5) c[:1] = [] print a print b print c print d print e print f
Answers:
[1, 2, 5] [1, 2] [7, [1, 2, 5] [6, 7, [1, 2, 5]] [1, 2, 6, 7, [1, 2, 5]] [[7, [1, 2, 5]], [6, 7, [1, 2, 5]]]
mystery function returns a dictionary that maps ______________ to ______________."
def mystery(x):
a = {}
for y in x.split():
z = y[0]
if z not in a:
a[z] = []
a[z].append(y)
return a
Answer:
"...a dictionary that maps each letter to a list of the words in x that begin with that letter."
b = 5, 6 c, d = b a = b, c
a at this point? a += 2, what would happen to the value of a?a += b, what would happen to the value of a?a.append(b), what would happen to the value of a?Answers:
a is the two-element tuple ((5, 6), 5).TypeError because tuples cannot be added to integers. The value of a would remain unchanged.a would become ((5, 6), 5, 5, 6).AttributeError because tuples do not have an append method. The value of a would remain unchanged.Function A (supposed to print the last value):
oldvalue = None def change_to(newvalue): print 'previous value was', oldvalue oldvalue = newvalue
Function B (supposed to print a list of all previous values):
oldvalues = [] def change_to(newvalue): print 'all previous values were', oldvalues oldvalues.append(newvalue)
Answers:
Function A contains the bug. The assignment oldvalue = newvalue makes oldvalue refer to a local variable, not the global variable that was set to None. Every time change_to is called, oldvalue will be a new unbound local variable and the print statement will cause a NameError. Insert the declaration global oldvalue at the beginning of the change_to function to fix the bug.
Function B works correctly as given, because oldvalues.append(newvalue) is a method call, not an assignment. Since there are no assignments to oldvalues, oldvalues refers to the global variable and persists between calls to change_to as intended.
These programs will give you experience converting between units using Python (which will exercise your understanding of collections) and basic web fetching to highlight the power of using the web in your programs (and show you how easy it is to do in Python).
In programming assignment 2b, you learned how to pass data to and from a website. For this quiz, you will learn about how Python reads and writes information to files, otherwise known as Input and Output (I/O). Thankfully, there's not much reading in this section.
input.txt contains a list of one or more floating-point numbers, with one on each line. An aspiring Python programmer wrote the following program to calculate the average of these numbers and write it to output.txt. However, the program has four bugs. Describe each of the bugs and write out a fixed version of program below.
file = open('input.txt')
total = 0.0
count = 0
while 1:
line = file.readline()
total += line
count += 1
file.close()
file = open('output.txt')
file.write(total/count)
file.close()
Answer:
while loop.file.write().
file = open('input.txt')
total = 0.0
count = 0
while 1:
line = file.readline()
if not line: # Fix bug 1.
break # Fix bug 1.
total += float(line) # Fix bug 2.
count += 1
file.close()
file = open('output.txt', 'w') # Fix bug 3.
file.write('%f\n' % (total/count)) # Fix bug 4.
file.close()
Alternatively, bug 1 can also be fixed by replacing the lines
while 1: line = file.readline()
with the single line
for line in file:
This program will give you experience with CGI programming and Client/Server processing. Specifically:
For this quiz, you will learn about object-oriented programming in Python:
Counter class that supports the following interaction:
>>> c1 = Counter() ## default is to start counting from 0 >>> c1.numCountersMade 1 ## Only c1 so far >>> c2 = Counter(100) >>> print(c1) Counter: 0 >>> print(c2) Counter: 100 >>> c1.increment() >>> print(c1) Counter: 1 >>> print(c2) Counter: 100 >>> c1.numCountersMade 2 ## We've only made c1 and c2 so far >>> c2.clear() >>> print(c2) Counter: 0
Answer:
Here are thoughts as we approach the solution
numCountersMade in a Class Variable so that as we make more Counters, it gets updated__init__ needs to be optional with a default value of 0__str__, since print knows what to do with a Counterincrement() and clear()
class Counter: '''A simple counter''' numCountersMade = 0 def __init__(self, count = 0): '''Make a new counter''' self.count = count Counter.numCountersMade += 1 def __str__(self): '''Override str''' return "Counter: " + str(self.count) def increment(self): '''Increment counter''' self.count += 1 def clear(self): '''Clear counter back to 0''' self.count = 0
Umpire class that can track the count of a hitter. Note, we wrote this code in a rush, there may be bugs in it! Your job is to find them and identify whether they are syntax, logical, or style bugs, then correct all the bugs.
class Umpire '''A baseball umpire''' def __init__(self): '''Make a new umpire''' self.balls = self.strikes = Counter() def __str__(self): '''Printed representation of an Umpire''' ### Want something like "3 balls, 2 strikes" print self.balls + " balls, " + self.strikes + " strikes" def strike(self): '''Register a strike, reset if 3 strikes''' self.strikes++ if self.strikes.count == 3: clear(self) print "Strikeout" def ball(self) '''Register that we had a ball''' self.balls.increment() if self.balls.count == 4 self.clear() print "Take your bases...a walk!" def clear(self): '''Clear the umpire counters''' self.balls.clear() self.strikes.count = 0
Answer:
Here are the problems we found (the corrected solution is below)
Counter module if we're to use it in Umpireballs and strikes need to be different Counters, and not share the same CounterCounter() initialiazation method (__init__) in the Counter class, we need to call Counter.Counter()self.balls.count to get the number, not self.balls (an object), and we need to surround it with a str callself.strikes is an object, and the ++ operator is from C/C++/Java, not Python.clear will result in a NameError, since without the "self." it will look in the global namespace.count will work given the current implementation of Counter, you are exploiting Python's "weakness" in its inability to limit access of its local instance variables from the outside. What if Counter.clear() were rewritten to effect other internal state in addition to zeroing out the clear variable? You'd be missing that, which would be a hard bug to track down. It's like going to a restaurant by coming through the back entrance in the kitchen...you sometimes miss the flyers they hand out at the door. Lesson: Always use official accessors ("setters" and "getters") when provided -- follow the Application Programming Interface (API), otherwise known as "specs". Granted, Counter doesn't provide a getter, and it probably should, but we can't change that in Umpire.
import Counter ### bug 1 class Umpire: ### bug 2 '''A baseball umpire''' def __init__(self): '''Make a new umpire''' self.balls = Counter.Counter() ### bugs 3, 4 self.strikes = Counter.Counter() ### bugs 3, 4 def __str__(self): '''Printed representation of an Umpire''' ### Want something like "3 balls, 2 strikes" return str(self.balls.count) + " balls, " + str(self.strikes.count) + " strikes" ### bug 5 def strike(self): '''Register a strike, reset if 3 strikes''' self.strikes.increment() ### bug 6 if self.strikes.count == 3: self.clear() ### bug 7 print "Strikeout" def ball(self): ### bug 2 '''Register that we had a ball''' self.balls.increment() if self.balls.count == 4: ### bug 2 self.clear() print "Take your bases...a walk!" def clear(self): '''Clear the umpire counters''' self.balls.clear() self.strikes.clear() ### bug 8
This program will give you experience with object-oriented programming in Python:
...by having you assign cool behavior to Turtles in a small artificial life program. Don't panic, we've done most of the heavy lifting for you!
For this quiz, you will learn about Tkinter and event-based programming in Python:
from Tkinter import * Button(text="L").pack (side=LEFT, expand=YES, fill=BOTH) Button(text="T").pack (side=TOP, expand=YES, fill=BOTH) Button(text="R").pack (side=RIGHT, expand=YES, fill=BOTH) Button(text="B").pack (side=BOTTOM, expand=YES, fill=BOTH) Button(text="LL").pack(side=LEFT, expand=YES, fill=BOTH) Button(text="TT").pack(side=TOP, expand=YES, fill=BOTH) mainloop()
Answer:


Answer:
from Tkinter import * clicks=0 def clicker(): global clicks clicks += 1 lab.config(text=clicks) Button(text="Click me", command=clicker).pack() lab = Label(text=clicks) lab.pack(side=LEFT) Label(text=" clicks").pack() mainloop()
Answer:
There are many possible answers, but we believe the best is that one can customize an existing widget in a very interesting way (ala "Styles" in Microsoft Word) as a new class, and then use many instances in the final GUI. All the instances will have the same customization. If we didn't define a new class, then we'd have to apply the customization to each of the instances individually. These new classes can now be used by anyone, not just your program! Think software reuse!
import Tkinter def quit(): print "goodbye..." import sys; sys.exit() Label(text="Demo GUI") b = Button(text="Quit").pack(fill=yes) b.config(command=quit) root.mainloop()
Answer:
Here are the problems we found (the corrected solution is below)
pack doesn't return a widget
import Tkinter ### bug 1 def quit(): print "goodbye..." import sys; sys.exit() Tkinter.Label(text="Demo GUI").pack() ### bug 2,3 b = Tkinter.Button(text="Quit") ### bug 2,4 b.config(command=quit) b.pack(expand=Tkinter.YES) ### bug 5,6,7 ## Alternatively you collapse the above three lines into one with ## Tkinter.Button(text="Quit", command=quit).pack(expand=Tkinter.YES) b.mainloop() ### bug 8
...or...
from Tkinter import * ### bug 1 def quit(): print "goodbye..." import sys; sys.exit() Label(text="Demo GUI").pack() ### bug 3 b = Button(text="Quit") ### bug 4 b.config(command=quit) b.pack(expand=YES) ### bug 5,6 ## Alternatively you collapse the above three lines into one with ## Tkinter.Button(text="Quit", command=quit).pack(expand=YES) mainloop() ### bug 8
This program will give you experience with Tkinter and event-based programming in Python by asking you to modify the GUI we handed you in the Turtle Behavior project.