The = , augmented = and del Statements
Variables hold the state of our program. In Variables we’ll introduce variables, then in The Assignment Statement we’ll cover the basic assignment statement for changing the value of a variable. This is followed by an exercise section that refers back to exercises from Simple Numeric Expressions and Output. In Input Functions we introduce some primitive interactive input functions that are built-in. This is followed by some simple exercises that build on those from section The Assignment Statement. We’ll cover the multiple assignment statement in Multiple Assignment Statement. We’ll round on this section with the del statement, for removing variables in The del Statement.
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:
a pi aVeryLongName a_name __str__ _hidden
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.
When we introduce functions in Functions, classes in Classes and modules in Components, Modules and Packages, we’ll revisit this namespace technique for managing scope. In particular, see Functions and Namespaces for a digression on this.
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.
We create and change variables primarily with the assignment statement. This statement provides an expression and a variable name which will be used to label the value of the expression.
variable = expression
Here’s a short script that contains some examples of assignment statements.
#!/usr/bin/env python # Computer the value of a block of stock shares= 150 price= 3 + 5.0/8.0 value= shares * price print value
Since this file is new, we’ll need to do the chmod +x example3.py once, after we create this file. Then, when we run this progam, we see the following.
$ ./example3.py 543.75
Any of the usual arithmetic operations can be combined with assignment to create an augmented assignment statement.
For example, look at this augmented assignment statement:
a += v
This statement is a shorthand that means the same thing as the following:
a = a + v
Here’s a larger example
#!/usr/bin/env python # Total value of a portfolio made up of two blocks of stock portfolio = 0 portfolio += 150 * 2 + 1/4.0 portfolio += 75 * 1 + 7/8.0 print portfolio
First, we’ll do the chmod +x portfolio.py on this file. Then, when we run this progam, we see the following.
$ ./portfolio.py 376.125
The other basic math operations can be used similarly, although the purpose gets obscure for some operations. These include -=, *=, /=, %=, &=, ^=, |=, <<= and >>=.
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.
#!/usr/bin/env python # Compute the odds of winning on the first roll win = 0 win += 6/36.0 # ways to roll a 7 win += 2/36.0 # ways to roll an 11 print "first roll win", win # Compute the odds of losing on the first roll lose = 0 lose += 1/36.0 # ways to roll 2 lose += 2/36.0 # ways to roll 3 lose += 1/36.0 # ways to roll 12 print "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 1 point -= win # remove odds of winning point -= lose # remove odds of losting print "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 = 0 point += 2*3/36.0 # ways to roll 4 or 10 point += 2*4/36.0 # ways to roll 5 or 9 point += 2*5/36.0 # ways to roll 6 or 8 print point
By the way, you can add the statement print win + 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.
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.
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.
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.
In Python 3, the raw_input() function will be renamed to input().
The Python 2 input() function will be removed. It’s that useless.
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 import readline. 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 import rlcompleter. 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.
If a prompt is present, it is written to sys.stdout.
Input is read from sys.stdin and returned as a string.
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.
Here’s an example script that uses raw_input().
#!/usr/bin/env python # show how raw_input works a= raw_input( "yes?" ) print "you said", a
When we run this script from the shell prompt, it looks like the following.
MacBook-3:Examples slott$ python rawdemo.py yes?why not? you said why not?
If we want numeric input, we must convert the resulting string to a number.
#!/usr/bin/env python # Compute the value of a block of stock shares = int( raw_input("shares: ") ) price = float( raw_input("dollars: ") ) price += float( raw_input("eights: ") )/8.0 print "value", shares * price
We’ll chmod +x stock.py this program; then we can run it as many times as we like to get results.
MacBook-3:Examples slott$ ./stock.py shares: 150 dollars: 24 eights: 3 value 3656.25
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.
As a teaser, here’s what it looks like.
MacBook-5:Examples slott$ python stock.py shares: a bunch Traceback (most recent call last): File "stock.py", line 3, in <module> shares = int( raw_input("shares: ") ) ValueError: invalid literal for int() with base 10: 'a bunch'
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.
This function will be removed. It’s best not to make use of it.
The value of the input() function is eval( raw_input( prompt ) ).
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.
#!/usr/bin/env python # Compute line between two points. x1,y1 = 2,3 # point one x2,y2 = 6,8 # point two m,b = float(y1-y2)/(x1-x2), y1-float(y1-y2)/(x1-x2)*x1 print "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,4 b,a = a,b print a,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:
del object 〈 , ... 〉
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.
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 >>> area 15.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.
>>> 335/113.0 2.9646017699115044 >>> 355/113.0 3.1415929203539825 >>> pi=_ >>> pi*2.2**2 15.205309734513278 >>> area=_ >>> area 15.205309734513278
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.
Extend Previous Exercises. Rework the exercises in Numeric Types and Expressions.
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:
#!/usr/bib/env python # Convert 8 C to F C=8 F=32+C*(9./5.) print "celsius",C,"fahrenheit",F
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 = 12 b = a*math.log(a) aVeryLongVariable = 26 d = 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: