[Tutor] Re: I'm just full of questions today

Daniel Yoo dyoo@hkn.eecs.berkeley.edu
Sun, 29 Oct 2000 00:30:45 -0700 (PDT)


> def PaddleMotion(dir, lpx1, lpx2, lpy1, lpy2):
>     if dir == 'left':
>         lpx1 = lpx1 - 30
>         lpx2 = lpx2 - 30
>     Screen.coords(paddle, lpx1, lpy1, lpx2, lpy2)
> 
> So it moves left.  I have to re-assign the values of everything again so
> that it will keep moving with repeating presses of the button.


That looks ok.  You can definitely make things look nicer if you apply
some OOP on that Paddle.  Here's a really quick sketch of what it might
look like:

####
class Paddle:
    def __init__(self, x1, x2, y1, y2):
        """Initialize a Paddle with inital coordinates 
           x1, x2, y1, and y2."""
        self.x1, self.x2, self.y1, self.y2 = x1, x2, y1, y2

    def move(self, offset):
        self.x1, self.x2 = self.x1 - offset, self.x2 - offset
###

Then you can create an instance of a paddle and use it to hold the
paddle's coordinates:

    mypaddle = Paddle(0, 10, 0, 3)  # construct a paddle
    mypaddle.move(-30)              # tell it to move -30
    print mypaddle.x1, mypaddle.x2  # and show the results of the move()



One other advantage of object orientation, and objects in general, is that
it'll allow you to escape a certain troublesome situation.  Let's take a
look at your function again:

> def PaddleMotion(dir, lpx1, lpx2, lpy1, lpy2):
>     if dir == 'left':
>         lpx1 = lpx1 - 30
>         lpx2 = lpx2 - 30
>     Screen.coords(paddle, lpx1, lpy1, lpx2, lpy2)

There's a small problem here becase any changes you make to lpx1, lpx2,
lpy1, and lpy2 will be local to PaddleMotion.  This might make more sense
with a short, unrelated example:

###
>>> def printSquare(x):
...     x = x * x
...     print x
... 
>>> num = 5
>>> printSquare(num)
25
>>> num
###

Notice that nothing happens to num.  That's because when we call
printSquare(num), Python does something like this:

    x = num  (now x contains the value of num, since num contains an
              "immutable" numeric type)
    x = x * x
    print x

Within that exchange of values to parameters, x gets a copy of whatever
num contained, and within the function, nothing happens to num.  This is
how local variables provide isolation; often, it's very helpful, but not
when you want a function to modify the state of a set of variables.


One way to fix this is to explicitly return those values back with the
return statement:

###
def PaddleMotion(dir, lpx1, lpx2, lpy1, lpy2):
    if dir == 'left':
        lpx1 = lpx1 - 30
        lpx2 = lpx2 - 30
    Screen.coords(paddle, lpx1, lpy1, lpx2, lpy2)
    return (lpx1, lpx2, lpy1, lpy2)
###

and call PaddleMotion like this:

    x1,x2,y1,y2 = PaddleMotion('left', x1, x2, y1, y2)

But already this is a little long to read.  The easier approach is to
accumulate those coordinates into a class, and provide methods to change
the state of an instance.

Hope this helps!