As a procedural program makes progress through the steps from launch to completion,
it does so by undergoing changes of state. The state of our program as a
whole is the state of all of the program’s variables. When one variable
changes, the overall state has changed.

Variables are the names your program assigns to the results of an
expression. Every variable is created with an initial value. Variables
will change to identify new objects and the objects identified by a
variable can change their internal state. These three kinds of state
changes (variable creation, object assignment, object change) happen as
inputs are accepted and our program evaluates expressions. Eventually
the state of the variables indicates that we are done, and our program
can exit.

A Python variable name must be at least one letter, and can have a
string of numbers, letters and _‘s to any length. Names that
start with _ or __ have special significance. Names that
begin with _ are typically private to a module or class. We’ll
return to this notion of privacy in Classes and Modules.
Names that begin with __ are part of the way the Python
interpreter is built.

Example variable names:

apiaVeryLongNamea_name__str___hidden

Tip

Tracing Execution

We can trace the execution of a program by simply following the
changes of value of all the variables in the program. For
programming newbies, it helps to create a list of variables and
write down their changes when studying a program. We’ll show
an example in the next section.

Python creates new objects as the result of evaluating an expression.
Python assigns these objects to new variables with an assignment statement.
Python removes variables with a del statement. The underlying object
is later garbage-collected when there are no more variables referring to the
object.

Some Consequences. A Python variable is little more than a name which
refers to an object. The central issue is to recognize that the
underlying object is the essential part of our program; a variable name
is just a meaningful label. This has a number of important consequences.

One consequence of a variable being simply a label is that any number of
variables can refer to the same object. In other languages (C, C++,
Java) there are two kinds of values: primitive and objects, and there
are distinct rules for handling the two kinds of values. In Python,
every variable is a simple reference to an underlying object. When
talking about simple immutable objects, like the number 3, multiple
variables referring to a common object is functionally equivalent to
having a distinct copy of a primitive value. When talking about mutable
objects, like lists, mappings, or complex objects, distinct variable
references can change the state of the common object.

Another consequences is that the Python object fully defines it’s own type.
The object’s type defines the representation, the range of values and
the allowed operations on the object. The type is established when the
object is created. For example, floating point addition and long integer
objects have different representations, operations of adding these kinds
of numbers are different, the objects created by addition are of
distinct types. Python uses the type information to choose which
addition operation to perform on two values. In the case of an
expression with mixed types Python uses the type information to coerce
one or both values to a common type.

This also means the “casting” an object to match the declared type
of a variable isn’t meaningful in Python. You don’t use C++ or Java-style
casting.

We’ve already worked with the four numeric types: plain integers, long
integers, floating point numbers and complex numbers. We’ve touched on
the string type, also. There are several other built-in types that we
will look at in detail in Data Structures. Plus, we can use class
definitions to define new types to Python, something we’ll look at in Data + Processing = Objects.

We commonly say that a static language associates the type
information with the variable. Only values of a certain type can be
assigned to a given variable. Python, in contrast, is a dynamic
language; a variable is just a label or tag attached to the object. Any
variable can be associated with an object of any type.

The final consequence of variables referring to objects is that a
variable’s scope can be independent of the object itself. This means
that variables which are in distinct namespaces can refer to the same
object. When a function completes execution and the namespace is
deleted, the variables are deleted, and the number of variables
referring to an object is reduced. Additional variables may still refer
to an object, meaning that the object will continue to exist. When only
one variable refers to an object, then removing the last variable
removes the last reference to the object, and the object can be removed
from memory.

Also note that expressions generally create new objects; if an object
is not saved in a variable, it silently vanishes. We can safely ignore
the results of a function.

Scope and Namespaces. A Python variable is a name which refers to an
object. To be useful, each variable must have a scope of
visibility. The scope is defined as the set of statements that can make
use of this variable. A variable with global scope can be
referenced anywhere. On the other hand, a variable with local scope
can only be referenced in a limited suite of statements.

This notion of scope is essential to being able to keep a intellectual
grip on a program. Programs of even moderate complexity need to keep
pools of variables with separate scopes. This allows you to reuse
variable names without risk of confusion from inadvertantly changing the
value of a variable used elsewhere in a program.

Python collects variables into pools called namespaces . A
new namespace is created as part of evaluating the body of a function or
module, or creating a new object. Additionally, there is one global
namespace. This means that each variable (and the state that it implies)
is isolated to the execution of a single function or module. By
separating all locally scoped variables into separate namespaces, we
don’t have an endless clutter of global variables.

In the rare case that you need a global variable, the global
statement is available to assign a variable to the global namespace.

Assignment is fundamental to Python; it is how the objects created by an
expression are preserved. We’ll look at the basic assignment statement,
plus the augmented assignment statement. Later, in Multiple Assignment Statement,
we’ll look at multiple assignment.

In craps, the first roll of the dice is called the “come out roll”.
This roll can be won immediately if the number is 7 or 11. It can be lost
immediately if the number is 2, 3 or 12. All of the remaining numbers will establish a
point and the game continues.

craps.py

#!/usr/bin/env python# Compute the odds of winning on the first rollwin=0win+=6/36.0# ways to roll a 7win+=2/36.0# ways to roll an 11print"first roll win",win# Compute the odds of losing on the first rolllose=0lose+=1/36.0# ways to roll 2lose+=2/36.0# ways to roll 3lose+=1/36.0# ways to roll 12print"first roll lose",lose# Compute the odds of rolling a point number (4, 5, 6, 8, 9 or 10)point=1# odds must total to 1point-=win# remove odds of winningpoint-=lose# remove odds of lostingprint"first roll establishes a point",point

There’s a 22.2% chance of winning, and a 11.1% chance of losing. What’s
the chance of establishing a point? One way is to figure that it’s
what’s left after winning or loosing. The total of all probabilities
always add to 1. Subtract the odds of winning and the odds of losing and
what’s left is the odds of setting a point.

Here’s another way to figure the odds of rolling 4, 5, 6, 8, 9 or 10.

point=0point+=2*3/36.0# ways to roll 4 or 10point+=2*4/36.0# ways to roll 5 or 9point+=2*5/36.0# ways to roll 6 or 8printpoint

By the way, you can add the statement printwin+lose+point
to confirm that these odds all add to 1. This means that we have defined
all possible outcomes for the come out roll in craps.

Tip

Tracing Execution

We can trace the execution of a program by simply following the
changes of value of all the variables in the program.

We can step through the planned execution of our Python source statements, writing down the
variables and their values on a sheet of paper. From this, we can see the state
of our calculation evolve.

When we encounter an assignment statement, we look on our paper for
the variable. If we find the variable, we put a line through the old value
and write down the new value. If we don’t find the variable, we add it to
our page with the initial value.

Here’s our example from craps.py script
through the first part of the script. The win variable
was created and set to 0, then the value was replaced with
0.16, and then replaced with 0.22. The
lose variable was then created and set to
0. This is what our trace looks like so far.

win:

0.0

0.16

0.22

lose:

0

Here’s our example when craps.py script is
finished. We changed the variable lose several times.
We also added and changed the variable point.

win:

0.0

0.16

0.22

lose:

0.0

0.027

0.083

0.111

point:

1.0

0.77

0.66

We can use this trace technique to understand what a program means and how
it proceeds from its initial state to its final state.

As with many things Python, there is some additional subtlety to assignment,
but we’ll cover those topics later. For example, multiple-assignment
statement is something we’ll look into in more deeply in Tuples.

Python provides two simplistic built-in functions to accept input and
set the value of variables. These are not really suitable for a complete
application, but will do for our initial explorations.

Typically, interactive programs which run on a desktop use a complete
graphic user interface (GUI), often written with the
Tkinter module or the pyGTK module.
Interactive programs which run over the Internet use HTML forms.

The primitive interactions we’re showing with input() and raw_input()
are only suitable for very simple programs.

Note that some IDE’s buffer the program’s output, making these functions
appear to misbehave. For example, if you use Komodo, you’ll need to use
the “Run in a New Console” option. If you use BBEdit, you’ll have to use
the “Run in Terminal” option.

You can enhance these functions somewhat by including the statement
importreadline. This module silently and automatically
enhances these input functions to give the user the ability to scroll
backwards and reuse previous inputs.

You can also importrlcompleter. This module allows you to
define sophisticated keyword auto-completion for these functions.

The first way to get interactive input is the raw_input()
function. This function accepts a string parameter, which is the user’s
prompt, written to standard output. The next line available on standard
input is returned as the value of the function.

The raw_input() function reads from a
file often called sys.stdin. When running from the command-line,
this will be the keyboard, and what you type will be echoed in the
command window or Terminal window. If you try, however,
to run these examples from Textpad, you’ll see that Textpad doesn’t have
any place for you to type any input. In BBEdit, you’ll need to use the
Run In Terminal item in the #! menu.

The raw_input() mechanism is very limited. If the string
returned by raw_input() is not suitable for use by int(),
an exception is raised and the program stops running. We’ll cover
exception handling in detail in Exceptions.

In addition to the raw_input() function, which returns the
exact string of characters, there is the input()
function. This applies the eval() function to the input,
which will typically convert numeric input to the appropriate objects.

The basic assignment statement can do more than assign the result of a
single expression to a single variable. The assignment satement can also
assign multiple variables at one time.

The essential rule is that the left and
right side must have the same number of elements.

For example, the following script has several examples of multiple assignment.

line.py

#!/usr/bin/env python# Compute line between two points.x1,y1=2,3# point onex2,y2=6,8# point twom,b=float(y1-y2)/(x1-x2),y1-float(y1-y2)/(x1-x2)*x1print"y=",m,"*x+",b

When we run this program, we get the following output

MacBook-3:Examples slott$ ./line.py
y = 1.25 *x+ 0.5

We set variables x1, y1, x2 and y2.
Then we computed m and b from those four
variables. Then we printed the m and b.

The basic rule is that Python evaluates the entire right-hand side of the
= statement. Then it matches values with destinations on the
left-hand side. If the lists are different lengths, an exception is
raised and the program stops.

Because of the complete evaluation of the right-hand side, the following
construct works nicely to swap to variables. This is often quite a bit
more complicated in other languages.

a,b=1,4b,a=a,bprinta,b

We’ll return to this in Tuples, where we’ll see
additional uses for this feature.

An assignment statement creates or locates a variable and
then assigns a new object to the variable. This change in state is how
our program advances from beginning to termination. Python also provides
a mechanism for removing variables, the del statement.

The del statement looks like this:

delobject 〈 , ... 〉

Each object
is any kind of Python object. Usually these are variables, but they can
be functions, modules or classes.

The del statement works by unbinding the name,
removing it from the set of names known to the Python interpreter. If
this variable was the last remaining reference to an object, the object
will be removed from memory. If, on the other hand, other variables
still refer to this object, the object won’t be deleted.

C++ Comparison

Programmers familiar with C++ will be pleased to note that memory
management is silent and automatic, making programs much more
reliable with much less effort. This removal of objects is called
garbage collection, something that can be rather
difficult to manage in larger applications. When garbage collection
is done incorrectly, it can lead to dangling references:
a variable that refers to an object that was deleted prematurely.
Poorly designed garbage collection can also lead to
memory leaks, where unreferenced objects are not
properly removed from memory. Because of the automated garbage
collection in Python, it suffers from none of these memory
management problems.

The del statement is typically used only in rare, specialized
cases. Ordinary namespace management and garbage collection are
generally sufficient for most purposes.

When we first looked at interactive Python in Command-Line Interaction
we noted that Python executes assignment statements silently, but prints
the results of an expression statement. Consider the following example.

>>> pi=355/113.0>>> area=pi*2.2**2>>> area15.205309734513278

The first two inputs are complete statements, so there is no response.
The third input is just an expression, so there is a response.

It isn’t obvious, but the value assigned to pi isn’t correct.
Because we didn’t see anything displayed, we didn’t get any feedback
from our computation of pi.

Python, however, has a handy way to help us. When we type a simple
expression in interactive Python, it secretly assigns the result to a
temporary variable named _. This isn’t a part of scripting,
but is a handy feature of an interactive session.

This comes in handy when exploring something rather complex. Consider
this interactive session. We evaluate a couple of expressions, each of
which is implicitly assigned to _. We can then save the
value of _ in a second variable with an easier-to-remember
name, like pi or area.

Note that we created a floating point object (2.964...), and Python
secretly assigned this object to _. Then, we computed a new
floating point object (3.141...), which Python assigned to _.

What happened to the first float, 2.964...? Python garbage-collected
this object, removing it from memory.

The second float that we created (3.141) was assigned to _.
We then assigned it to pi, also, giving us two references to
the object. When we computed another floating-point value (15.205...),
this was assigned to _.

Does this mean our second float,
3.141... was garbage collected? No, it wasn’t garbage collected; it was
still referenced by the variable pi.

Each of the previous exercises can be rewritten to use variables
instead of expressions using only constants. For example, if you
want to tackle the Fahrenheit to Celsius problem, you might write
something like this:

You’ll want to rewrite these exercises using variables to get ready
to add input functions.

State Change. Is it true that all programs simply establish a state?

It can argued that a controller for a device (like a toaster or a
cruise control) simply maintains a steady state. The
notion of state change as a program moves toward completion doesn’t
apply because the software is always on. Is this the case, or does
the software controlling a device have internal state changes?

For example, consider a toaster with a thermostat, a “browness”
sensor and a single heating element. What are the inputs? What are
the outputs? Are there internal states while the toaster is making toast?

Refer back to the exercises in Numeric Types and Expressions for
formulas and other details. Each of these can be rewritten to use
variables and an input conversion. For example, if you want to tackle
the Fahrenheit to Celsius problem, you might write something like this:

C=raw_input('Celsius: ')F=32+C*(9./5.)print"celsius",C,"fahrenheit",F

Stock Value. Input the number of shares, dollar price and number
of 8th’s. From these three inputs, compute the total dollar value of
the block of stock.

Convert from |deg| C to |deg| F. Write a short program that will input ° C
and output ° F. A second program will input ° F and output ° C.

Periodic Payment. Input the principal, annual percentage rate and
number of payments. Compute the monthly payment. Be sure to divide
rate by 12 and multiple payments by 12.

Surface Air Consumption Rate. Write a short program will input the
starting pressure, final pressure, time and maximum depth. Compute
and print the SACR.

A second program will input a SACR, starting pressure, final
pressure and depth. It will print the time at that depth, and the
time at 10 feet more depth.

Wind Chill. Input a temperature and a wind speed. Output the wind chill.

Force from a Sail. Input the height of the sail and the length.
The surface area is 1/2 × h × l. For a wind speed of 25 MPH, compute the
force on the sail. Small boat sails are 25-35 feet high and 6-10
feet long.

Spaces are used sparingly in Python. It is common to put spaces around
the assignment operator. The recommended style is

c=(f-32)*5/9

Do not take great pains to line up assignment operators vertically. The
following has too much space, and is hard to read, even though it is
fussily aligned.

a=12b=a*math.log(a)aVeryLongVariable=26d=13

This is considered poor form because Python takes a lot of its look from
natural languages and mathematics. This kind of horizontal whitespace is
hard to follow: it can get difficult to be sure which expression lines
up with which variable. Python programs are meant to be reasonably
compact, more like reading a short narrative paragraph or short
mathematical formula than reading a page-sized UML diagram.

Variable names are often given as mixedCase; variable names
typically begin with lower-case letters. The lower_case_with_underscores
style is also used, but is less popular.

In addition, the following special forms using leading or trailing
underscores are recognized:

single_trailing_underscore_: used to avoid conflicts
with Python keywords. For example: print_=42

__double_leading_and_trailing_underscore__: used for
special objects or attributes, e.g. __init__, __dict__
or __file__. These names are reserved; do not use names
like these in your programs unless you specifically mean a
particular built-in feature of Python.