Variables Top Conditionals Contents

Assignment

Once a variable has been created, it is possible to change its value, or binding, using the assignment operator. Consider the following interaction with the interpreter:

    >>> BLACK = 1            # creation
    >>> BROWN = 2            # creation
    >>> GREEN = 3            # creation
    
    >>> eyeColor = BLACK     # creation
    
    >>> eyeColor             # reference
    1
    
    >>> eyeColor = GREEN     # assignment!
    
    >>> eyeColor == BLACK    # equality
    False
    
    >>> eyeColor == BROWN    # equality
    False

    >>> eyeColor == GREEN    # equality
    True

Note that the # sign is the comment character in Python; it and any following characters on the line are ignored.

The operator/variable = (equals sign) is bound to the assignment function. The assignment function, however, is not like the operators + and *. Recall that + and the like evaluate the things on either side (recall that those things on either side are generically known as operands) before combining them. For =, the left operand is not evaluated: (if it were, the assignment

    eyeColor = GREEN

would attempt to assign the value of 1 to be 3. In general, an operator which does not evaluate all its arguments is known as a special form.

The last two expressions given to the interpreter in the previous interaction refer to the == (equality) operator. This == operator returns true if its operands refer to the same thing and false otherwise.

Another thing to note in the above interaction is that the variables BLACK, GREEN, and BROWN are not meant to change from their initial values. We denote variables whose values aren't supposed to change by naming the variable using (mostly) capital letters (this convention is borrowed from earlier programming languages). The use of caps emphasizes the constant nature of the (not too) variable.

In the above interaction with the interpreter, we use the integers 1, 2, and 3 to represent the colors black, brown, and green. By abstracting 1, 2, and 3 and giving them meaningful names (i.e., BLACK, BROWN, and GREEN) we find it easy to read code that assigns and tests eye color. We do this because it is difficult to remember which integer is assigned to which color. Without the variables BLACK, BROWN, and GREEN, we have to keep little notes somewhere to remind ourselves what's what. Here is an equivalent interaction with the interpreter without the use of the variables BLACK, GREEN, and BROWN.

    >>> eyeColor = 1
    1
    
    >>> eyeColor
    1
    
    >>> eyeColor = 3
    3
    
    >>> eyeColor == 2
    False
    
    >>> eyeColor == 3
    True

In this interaction, the meaning of eyeColor is not so obvious. We know its a 3, but what eye color does 3 represent? When numbers appear directly in code, they are referred to as magic numbers because they obviously mean something and serve some purpose, but how they make the code work correctly is not always readily apparent, much like a magic trick. Magic numbers are to be avoided. Using well-name constants (or variables if constants are not part of the programming language) is considered stylistically superior.

Precedence and Associativity of Assignment

Assignment has the lowest precedence among the binary operators. It is also right associative. The right associativity allows for statements like

    a = b = c = d = 0

which conveniently assigns a zero to four variables at once and, because of the right associative nature of the operator, is equivalent to:

    (a = (b = (c = (d = 0))))

The resulting value of an assignment operation is the value assigned, so the assignment d = 0 returns 0, which is, in turn, assigned to c and so on.

Assignment and Arrays

You can change a particular element of a array by assigning a new value to the index of that element by using bracket notation:

    >>> items = ['a', True, 7]

    >>> items[0] = 'b'

    >>> items
    ['b', True, 7]`

As expected, assigning to index 0 replaces the first element. In the example, the first element 'a' is replaced with 'b'.

What bracket notation would you use to change the 7 in the array to a 13? The superior student will experiment with the Python interpreter to verify his or her guess.

Assignment Patterns

The art of writing programs lies in the ability to recognize and use patterns that have appeared since the very first programs were written. In this text, we take a pattern approach to teaching how to program. For the topic at hand, we will give a number of patterns that you should be able to recognize to use or avoid as the case may be.

The Transfer Pattern

The transfer pattern is used to change the value of a variable based upon the value of another variable. Suppose we have a variable named alpha which is initialized to 3 and a variable beta which is initialized to 10:

    alpha = 3
    beta = 10

Now consider the statement:

    alpha = beta

This statement is read like this: make the new value of alpha equal to the value of beta, throwing away the old value of alpha. What is the value of alpha after that statement is executed? Highlight the following line to see the answer:

The new value of alpha is 10.

The transfer pattern tells us that value of beta is imprinted on alpha at the moment of assignment but in no case are alpha and beta conjoined in anyway in the future. Think of it this way. Suppose your friend spray paints her bike neon green. You like the color so much you spray paint your bike neon green as well. This is like assignment: you made the value (color) of your bike the same value (color) as your friend's bike. Does this mean your bike and your friend's bike will always have the same color forever? Suppose your friend repaints her bike. Will your bike automatically become the new color as well? Or suppose you repaint your bike. Will your friend's bike automatically assume the color of your bike?

A graphical way to see this is to use the idea of a pointer. When a variable is assigned a value, we will say that variable points to the value. For the variables:

   alpha = 3
   beta = 10

a pointer diagram would look like:

Now when we assign alpha the value of beta:

    alpha = beta

we cross out alpha's pointer and replace it with a pointer to whatever beta points:

Note that we never point a variable to another variable; we only point variables to values10. To test your understanding, what happens if the following code is executed:

    alpha = 4
    beta = 13
    alpha = beta
    beta = 5

What are the final values of alpha and beta? Highlight the following line to see the answer:

The value of alpha is 13 and the value of beta is 5.

Here, the pointer diagram would look like:

where the picture on the left illustrates what things look like after alpha gets beta's value and the picture on the right after beta gets the value of 5.

To further test your understanding, what happens if the following code is executed:

    alpha = 4
    beta = 13
    alpha = beta
    alpha = 42

What are the final values of alpha and beta? Highlight the following line to see the answer:

The value of alpha is 42 and the value of beta is 13.

Here, the pointer diagram would look like:

where the picture on the left illustrates what things look like after alpha gets beta's value and the picture on the right after alpha gets the value of 42.

The Update Pattern

The update pattern is used to change the value of a variable based upon the original value of the variable. Suppose we have a variable named counter which is initialized to zero:

    counter = 0

Now consider the statement:

    counter = counter + 1

This statement is read like this: make the new value of counter equal to the old value of counter plus one. Since the old value is zero, the new value is one. Consider this sequence:

    counter = 0
    counter = counter + 1
    counter = counter + 1
    counter = counter + 1
    counter = counter + 1
    counter = counter + 1

What is the value of counter after the following code is executed? Highlight the following line to see the answer:

The value of counter is 5.

There is another form of this update:

    counter = 0
    counter += 5

The operator += says to update the variable on the left by adding in the value on the right to the current value of the variable.

The update pattern can be used to sum a number of variables. Suppose we wish to compute the sum of the variables a, b, c, d, and e. The obvious way to do this is with one statement:

    sum = a + b + c + d + e

However, we can use the update pattern as well:

    sum = 0
    sum = sum + a
    sum = sum + b
    sum = sum + c
    sum = sum + d
    sum = sum + e

If a is 1, b is 2, c is 3, d is 4, and e is 5, then the value of sum in both cases is 15. Why would we ever want to use the update pattern for computing a sum when the first version is so much more compact and readable? The answer is...you'll have to wait until we cover a programming concept called a loop. With loops, the update pattern is almost always used to compute sums, products, etc.

The Throw-away Pattern

The throw-away pattern is a mistaken attempt to use the update pattern. In the update pattern, we use the original value of the variable to compute the new value of the variable. Here again is the classic example of incrementing a counter:

    counter = counter + 1

In the throw-away pattern, the new value is computed but it the variable is not reassigned, nor is the new value stored anywhere. Many novice programmers attempt to update a counter simply by computing the new value:

    count + 1       # throw-away!

Python does all the work to compute the new value, but since the new value is not assigned to any variable, the new value is thrown away.

The Throw-away Pattern and Functions

The throw-away pattern applies to function calls as well. We haven't discussed functions much, but the following example is easy enough to understand. First we define a function that computes some value:

    def inc(x):
        return x + 1

This function returns a value one greater than the value given to it, but what the function actually does is irrelevant to this discussion. That said, we want to start indoctrinating you on the use of functions. Repeat this ten times:

We always do four things with functions: define them, call them, return something, and save the return value.

To call the function, we use the function name followed by a set of parentheses. Inside the parentheses, we place the value we wish to send to the function. Consider this code, which includes a call to the function inc:

    y = 4
    y = inc(y)
    print("y is",y)

If we were to run this code, we would see the following output:

    y is 5

The value of y, 4, is sent to the function which adds one to the given value and returns this new value. This new value, 5, is assigned back to y. Thus we see that y has a new value of 5.

Suppose, we run the following code instead:

    y = 4
    inc(y)
    print("y is",y)

Note that the return value of the function inc is not assigned to any variable. Therefore, the return value is thrown away and the output becomes:

    y is 4

The variable y is unchanged because it was never reassigned.

About Patterns

As you can see from above, not all patterns are good ones. However, we often mistakenly use bad patterns when programming. If we can recognize those bad patterns more readily, our job of producing a correctly working program is greatly simplified.

lusth@cs.ua.edu


Variables Top Conditionals Contents