Questions:
from my_library import * should be avoided; itβs better to indicate exactly what you want from him. This helps maintain a namespace without spaces.
you have one massive block of code; it is better to divide it into separate functions. This greatly facilitates thinking and debugging, and can help you reuse code later. Of course, this is a toy problem, you are not going to reuse it, but all you need to do is develop good habits, and factoring your code in this way is definitely a good habit! A general rule of thumb is that if a function contains more than a dozen lines of code, you should consider its further separation.
exercise asks you to track the current amounts of x, y, xx, and xy when you receive input points. I think this is kind of a bad idea - or at least more C-ish than Python-ish, because it forces you to do two different tasks at once (get points and do the math on them). My advice: if you get points, get points; if you do math, do math; do not try to do both at once.
Likewise, I don't like how you have a regression calculation, worrying about where the sides of the window are. Why should he know or care about windows? I hope you enjoy my solution :-)
Here is my reorganized version of your code:
from graphics import GraphWin, Point, Line, Rectangle, Text def draw_window() # create canvas win = GraphWin("Regression Line - Start Clicking!", 500, 500) win.setCoords(0., 0., 10., 10.) # exit button rect = Rectangle(Point(0.5, 0.1), Point(2.5, 2.1)) rect.setFill("red") rect.draw(win) Text(rect.getCenter(), "Done").draw(win) # instructions Text(Point(5., 0.5), "Click in this screen").draw(win) return win def get_points(win): points = [] while True: p = win.getMouse() p.draw(win) # clicked the exit button? px, py = p.getX(), p.getY() if 0.5 <= px <= 2.5 and 0.1 <= py <= 2.1: break else: points.append((px,py)) return points def do_regression(points): num = len(points) x_sum, y_sum, xx_sum, xy_sum = 0., 0., 0., 0. for x,y in points: x_sum += x y_sum += y xx_sum += x*x xy_sum += x*y x_mean, y_mean = x_sum/num, y_sum/num m = (xy_sum - num*x_mean*y_mean) / (xx_sum - num*x_mean*x_mean) def lineFn(xval): return y_mean + m*(xval - x_mean) return lineFn def main(): # set up win = draw_window() points = get_points(win) # show regression line lineFn = do_regression(points) Line( Point(0., lineFn(0. )), Point(10., lineFn(10.)) ).draw(win) # wait to close Text(Point(5., 5.), "Click to exit").draw(win) win.getMouse() win.close() if __name__=="__main__": main()
Hugh bothwell
source share