Like mathematicians, programmers frequently name values so that they can use them later. A name that refers to a value is called a variable. In Python, variable names can use letters, digits, and the underscore symbol (but they can’t start with a digit). For example, X, species5618, and degrees_celsius are all allowed, but 777 isn’t (it would be confused with a number), and neither is no-way! (it contains punctuation). Variable names are case sensitive, so ph and pH are two different names.
You create a new variable by assigning it a value:
| >>> degrees_celsius = 26.0 |
This statement is called an assignment statement; we say that degrees_celsius is assigned the value 26.0. That makes degrees_celsius refer to the value 26.0. We can use variables anywhere we can use values. Whenever Python sees a variable in an expression, it substitutes the value to which the variable refers:
| >>> degrees_celsius = 26.0 |
| >>> degrees_celsius |
| 26.0 |
| >>> 9 / 5 * degrees_celsius + 32 |
| 78.80000000000001 |
| >>> degrees_celsius / degrees_celsius |
| 1.0 |
Variables are called variables because their values can vary as the program executes. We can assign a new value to a variable:
| >>> degrees_celsius = 26.0 |
| >>> 9 / 5 * degrees_celsius + 32 |
| 78.80000000000001 |
| >>> degrees_celsius = 0.0 |
| >>> 9 / 5 * degrees_celsius + 32 |
| 32.0 |
Assigning a value to a variable that already exists doesn’t create a second variable. Instead, the existing variable is reused, which means that the variable no longer refers to its old value.
We can create other variables; this example calculates the difference between the boiling point of water and the temperature stored in degrees_celsius:
| >>> degrees_celsius = 15.5 |
| >>> difference = 100 - degrees_celsius |
| >>> difference |
| 84.5 |
We’re going to develop a model of computer memory—a memory model—that will let us trace what happens when Python executes a Python program. This memory model will help us accurately predict and explain what Python does when it executes code, a skill that is a requirement for becoming a good programmer.
Every location in the computer’s memory has a memory address, much like an address for a house on a street, that uniquely identifies that location. We’re going to mark our memory addresses with an id prefix (short for identifier) so that they look different from integers: id1, id2, id3, and so on.
Here is how we draw the floating-point value 26.0 using the memory model:
This image shows the value 26.0 at the memory address id1. We will always show the type of the value as well—in this case, float. We will call this box an object: a value at a memory address with a type. During execution of a program, every value that Python keeps track of is stored inside an object in computer memory.
In our memory model, a variable contains the memory address of the object to which it refers:
In order to make the image easier to interpret, we usually draw arrows from variables to their objects.
We use the following terminology:
Whenever Python needs to know which value degrees_celsius refers to, it looks at the object at the memory address that degrees_celsius contains. In this example, that memory address is id1, so Python will use the value at the memory address id1, which is 26.0.
Here is the general form of an assignment statement:
| variable = expression |
This is executed as follows:
Consider this example:
| >>> degrees_celsius = 26.0 + 5 |
| >>> degrees_celsius |
| 31.0 |
Here is how Python executes the statement degrees_celsius = 26.0 + 5:
Consider this code:
| >>> difference = 20 |
| >>> double = 2 * difference |
| >>> double |
| 40 |
| >>> difference = 5 |
| >>> double |
| 40 |
This code demonstrates that assigning to a variable does not change any other variable. We start by assigning value 20 to variable difference, and then we assign the result of evaluating 2 * difference (which produces 40) to variable double.
Next, we assign value 5 to variable difference, but when we examine the value of double, it still refers to 40.
Here’s how it works according to our rules. The first statement, difference = 20, is executed as follows:
Here is the current state of the memory model. (Variable double has not yet been created because we have not yet executed the assignment to it.)
The second statement, double = 2 * difference, is executed as follows:
Here is the current state of the memory model:
When Python executes the third statement, double, it merely looks up the value that double refers to (40) and displays it.
The fourth statement, difference = 5, is executed as follows:
Here is the current state of the memory model:
Variable double still contains id2, so it still refers to 40. Neither variable refers to 20 anymore.
The fifth and last statement, double, merely looks up the value that double refers to, which is still 40, and displays it.
We can even use a variable on both sides of an assignment statement:
| >>> number = 3 |
| >>> number |
| 3 |
| >>> number = 2 * number |
| >>> number |
| 6 |
| >>> number = number * number |
| >>> number |
| 36 |
We’ll now explain how Python executes this code, but we won’t explicitly mention memory addresses. Trace this on a piece of paper while we describe what happens; make up your own memory addresses as you do this.
Python executes the first statement, number = 3, as follows:
Evaluate the expression on the right of the = sign: 3. This one is easy to evaluate: 3 is produced.
Make the variable on the left of the = sign, number, refer to 3.
Python executes the second statement, number = 2 * number, as follows:
Evaluate the expression on the right of the = sign: 2 * number. number currently refers to 3, so this is equivalent to 2 * 3, and 6 is produced.
Make the variable on the left of the = sign, number, refer to 6.
Python executes the third statement, number = number * number, as follows:
Evaluate the expression on the right of the = sign: number * number. number currently refers to 6, so this is equivalent to 6 * 6, and 36 is produced.
Make the variable on the left of the = sign, number, refer to 36.
In this example, the variable score appears on both sides of the assignment statement:
| >>> score = 50 |
| >>> score |
| 50 |
| >>> score = score + 20 |
| >>> score |
| 70 |
This is so common that Python provides a shorthand notation for this operation:
| >>> score = 50 |
| >>> score |
| 50 |
| >>> score += 20 |
| >>> score |
| 70 |
An augmented assignment combines an assignment statement with an operator to make the statement more concise. An augmented assignment statement is executed as follows:
Evaluate the expression on the right of the = sign to produce a value.
Apply the operator attached to the = sign to the variable on the left of the = and the value that was produced. This produces another value. Store the memory address of that value in the variable on the left of the =.
Note that the operator is applied after the expression on the right is evaluated:
| >>> d = 2 |
| >>> d *= 3 + 4 |
| >>> d |
| 14 |
All the operators (except for negation) in Table 2, Arithmetic Operators Listed by Precedence from Highest to Lowest, have shorthand versions. For example, we can square a number by multiplying it by itself:
| >>> number = 10 |
| >>> number *= number |
| >>> number |
| 100 |
This code is equivalent to this:
| >>> number = 10 |
| >>> number = number * number |
| >>> number |
| 100 |
Table 3 contains a summary of the augmented operators you’ve seen plus a few more based on arithmetic operators you learned about in Expressions and Values: Arithmetic in Python.
Symbol |
Example |
Result | ||||
---|---|---|---|---|---|---|
+= |
|
x refers to 9 | ||||
-= |
|
x refers to 5 | ||||
*= |
|
x refers to 14 | ||||
/= |
|
x refers to 3.5 | ||||
//= |
|
x refers to 3 | ||||
%= |
|
x refers to 1 | ||||
**= |
|
x refers to 49 |