3.6. Variables

Variables are names that we introduce into a program to store data. We have already seen the simplest way in which this is done, with what is called an assignment statement:

>>> X = 3

An assignment statement may consist of references to other variables, as long as those other variables have already been introduced into the program:

>>> Y = 1
>>> Z = 2
>>> X = Y + Z

The left and right hand side of an assignment statement are thus different. The left hand side must consist of one name, which may be (but does not have to be) a name we have never seen before. The right hand side may be an expression of any degree of complexity.

One thing variables contrast with is literals. You may think of these as names whose reference is fixed by the definition of the language. These are expressions like:

>>>  1
1
>>>  2
2
>>>  "frog"
'frog'
>>> 1.0000000000000
1.0

Each of these is a perfectly valid expression and each is a legal line in a Python program, though none of them will get much done. In each case, Python responds the way it always does when you type in an expression that has a computable value, with the default way of printing that value. Thus, although you type “1.0000000000000”, Python evaluates this as something exactly equal to the float “1.0”, and prints it the way it usually prints that value.

So what we just learned is that Python provides fixed expressions (words) for naming any integer, string, or float, and these are just what you’d expect them to be. But don’t confuse the string “frog” with the name frog. When you start up the name frog is unknown:

Marks-MacBook-Pro:python_for_ss gawron$ python
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> frog
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'frog' is not defined
>>>

On the other hand the literal “frog”, like all strings, is a perfectly fine expression to type. Python knows what “frog” stands for. It stands for the string “frog”, which is particular piece of data, in fact a container containing 4 characters:

Marks-MacBook-Pro:python_for_ss gawron$ python
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "frog"
'frog'
>>>

Like any name, the name frog can be set to a value:

>>> frog = 1

And henceforth it refers to the same piece of data as the literal 1.

>>>  frog == 1
True

But the string “frog” cannot be set to a value, because the reference of the expression “frog” has been fixed once and for all, and Python will not let you change it:

>>> 'frog' = 1
File "<stdin>", line 1
SyntaxError: can't assign to literal

For the same reason, the following is a Syntax error, earning exactly the same error message:

>>> 1 = 1
File "<stdin>", line 1
SyntaxError: can't assign to literal

The reference of the symbol “1” is fixed by the rules of the language, and you are not allowed to change it. Note the following contrast, which is very important:

>>> 1 == 1
True
>>>

No error message. So “1 = 1” and “1 == 1” are different. They are what linguists call different kinds speech acts. One is a command and the other is an assertion. “1 = 1” can be paraphrased as the command “Set the value of the symbol ‘1’ to be 1”. This happens to be a command that Python will refuse to obey. The other expression ‘1 == 1’ is a claim: “The value of the expression ‘1’ is the same as the value of the expression ‘frog’. This looks less silly when the expressions on either side of the ‘==’ are different:

>>> frog == 1
True

The value returned is “True”, based on the fact that earlier in this Python session we set the value of the name frog to be 1.

A convenience of Python assignments, is that tuples of variables can be assigned values simultaneously:

>>> (x,y) = (2,3)

This is equivalent to

>>> x = 2
>>> y = 3

Except that it’s done simultaneously. For example, suppose we have the values of x and y as just set x=2 and y=3. Then if you want to swap the values of x and y, this works:

>>>  (x,y) = (y,x)
>>> x
3
>>> y
2

But with x=2 and y=3, successively setting x and y gets a different result:

>>> x = y
>>> y = x
>>> x
3
>>> y
3

In fact, simultanaeous assignment works with any Python iterable on the right hand side. For example, the following is legal:

>>> (x,y) = set(['freedonia','wonderland'])
>>> x
'wonderland'
>>> y
'freedonia'

This sets x to be one member of the set and y to be the other, and would only be useful if didn’t care which was x and which was y. As the example makes clear if the set is created from a sequence, the order of the elements in that sequence is lost in the set. If the set on the right hand side did not have exactly two members, a ValueError would be raised:

>>> (x,y) = set(['freedonia','wonderland','rohan'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack

Similarly, if the file foo looks like this:

a
b

the following produces a valid result, though it is very odd:

>>> (line1,line2) = open('foo','r')
>>> line1
'a\n'
>>> line2
'b\n'

This works because an open file handle is an iterable whose elements are the lines of the file. What makes it less than ideal is that the line elements in a file iterator include the next-line characters at the end of the line.