Variables, names, and the assignment operation

One of the most basic aspects of computer programming is assigning meaningful names to variables. It is particularly important in Python to remember that a variable name is just that--a name that refers to some underlying object.

In [1]:
a = 5.5  # line 1
b = a    # line 2
a = a ** 2   # line 3
print("a is", a, "and b is", b)
a is 30.25 and b is 5.5

No surprises here. You may be wondering whether you are wasting your time with this notebook. OK, try this:

In [2]:
# let 'a' be a 1-element list
a = [5.5]          # line 4
b = a              # line 5
a[0] = a[0] ** 2   # line 6
print("a is", a, "and b is", b)
a is [30.25] and b is [30.25]

Why did b change this time when we made a change to a?

In the first case, in line 1 we are saying a is a name for an immutable object, the floating point number with the value 5.5. In line 2, we assign b as another name for that same object. Next, in line 3 we make a new object, 5.5 squared, and re-assign the name a to this new object. But b still refers to the 5.5 object.

In the second case, in line 4 we are saying a is a name for a particular list object, which is mutable--its contents (the number 5.5) can be changed. In line 5, b is also a name for that same object. Now, in line 6, using the name a, we change the contents of the list. a and b are still names for the original list; we never made a new list, so any change to its contents can be seen or made via either of the two names, a or b.

The lesson is this: with variable assignment, you need to pay attention to when you are creating a brand-new object, versus when you are merely giving an existing object another name.

In the second case above, if you wanted b to be a new list--a copy of a--you could do it like this:

In [3]:
a = [5.5]
b = a[:]  # slicing a list returns a new list
a[0] = a[0] ** 2
print("a is", a, "and b is", b)
a is [30.25] and b is [5.5]

or like this:

In [4]:
a = [5.5]
b = list(a)
a[0] = a[0] ** 2
print("a is", a, "and b is", b)
a is [30.25] and b is [5.5]

Combined assignment and arithmetic operators

You don't have to use them, but you are likely to see constructs like the following:

In [5]:
a = 1
a += 3
print(a)
4

In [6]:
a *= 4
print(a)
16

In [7]:
# The % sign is the modulo division operator:
a %= 13
print(a)
3

Each of these is just a shorthand, e.g.

a += 3

is the same as

a = a + 3

and means "add 3 to the present contents of 'a' and then let 'a' be the name of the resulting object".

In [8]:
a = [1, 2]
b = a
# multiplying a list by a positive integer replicates its contents:
a *= 3
print("a is", a, "and b is", b)
a is [1, 2, 1, 2, 1, 2] and b is [1, 2, 1, 2, 1, 2]

Here, the scalar multiplication operation on the list did not make a new list, it changed the contents of the existing list; and again, 'b' is just another name for that list.

Multiple assignment: unpacking

Multiple assignments can be made in a single statement, like this:

In [9]:
a, b = 1, 2
c, d = (3, 4)
e, f = [5, 6]
g, h = [(7, 8), ("the", "end")]
print(a, b, c, d, e, f, g, h)
1 2 3 4 5 6 (7, 8) ('the', 'end')

Notice how the sequence types on the right are being unpacked. Of course, this only works if the number of elements on the right matches the number of names on the left.

This technique is not often used for ordinary variable assignments like those in the example above, but it is common for handling multiple return values from functions--a topic we will introduce shortly, in another notebook.

Identity versus equality

Make 3 variables, two of which point to the same list, and a third that points to a copy. Then use == to test for equality (same type of object and same contents) and is to test for identity (same object):

In [10]:
a = [1,2,3]
b = a
c = a[:]
print(a == b, a == c, b == c)
True True True

In [11]:
print(a is b, a is c, b is c)
True False False

In [12]:
d = (1,2,3)
print("Are ", a, "and", d, "equal?", a == d)
Are  [1, 2, 3] and (1, 2, 3) equal? False

In the last test we see that even if a list and a tuple have the same contents, they are not the same type of object, so they can't be equal.