Using Python

0. Introduction. Python is a scripting language for the rapid development of computer applications. It has a simple syntactical structure, yet it has many powerful extensions. You will have a chance to learn how to obtain Python, and how to use it for calculations. Python offers a form of extended-precision integer arithmetic which is very useful for performing high-precision integer calculations.

1. Obtaining Python Python is easy to obtain and, since it is an open-source technology, it is free. I will quickly summarize what you should to to get it for all major platorms.

The python.org site has many tutorials and resources to help you get started; explore the site and take a look at some of these. Our workshop will be done with IDLE on the Windows platform, so we will center on using that. However, the details of operating Python on other systems are similar.

2. Using Python as a Calculator First we will learn how to use Python interactvely. You should think of the "shell" as a telephone; you talk to Python and Python responds via the shell.

To invoke Python from IDLE, just double-click on the desktop alias or select Python -> IDLE from the Windows Start Menu.

You will see a blank window with a little red "Tk" in the upper left-hand corner, with "Untitled" in the title bar. Go to the Run menu and selecct Python Shell. This calls Python.

To invoke the Python shell directly in LINUX, just type

python

at the UNIX command line. This will put you directly into the interactive shell.

In either event, you will see this in the window.

Python 2.3.2 (#49, Oct  2 2003, 20:02:00) [MSC v.1200 32 bit (Intel)]
on win32
Type "copyright", "credits" or "license()" for more information.

****************************************************************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback 
interface.  This connection is not visible on any external
interface and no data is sent to or received from
the Internet.
****************************************************************
IDLE 1.0      
>>> 

You may see slightly different information, depending on the version of Python you have installed. The

>>>

is called the prompt It is the receiver you "speak" into to talk with Python. Let us begin with a simple command:

>>> 5*5

Python will politely reply with

25

You can use Python as a calculator. It supports standard floating point numbers, and it has the capability of managing extremly large integers. The operations *, + and - all work exactly as you expect them to. Python is aware of the rules of algebra and it obeys the PEMDAS order of operations. Here is an example session of calculation. The ** operator performs exponentiation. Try entering these then a few of your own.

>>>  (4+6)*5
50
>>>  2**100
1267650600228229401496703205376L
>>>  6-12
-6
>>>  3**5
243
Observe that the 2**100 triggered the use of extended-precision integers. Python appends an'L' on any extended-precision integer. Python also suppors the "mod" opeator %. To find b%a, Python divides a into b and returns the remainder.
>>> 356%7
1
>>> (2*5)%(3 + 1)
2

Python also supports scientific calculator functions, such as sqrt, sin, cos and exp. To use these, import the math module as in this example

>>> import math
>>> math.sqrt(5)
2.2360679774997898
>>> math.cos(3.14)
-0.9999987317275395
>>> math.acos(1)
0.0
You can see all of the mathematical functions that Python supports by looking in the Python documentation.

Division works a little differently than it does on a calculator. For floating point number, division works as expected. For integers, the quotient is truncated; this is integer division. You can always make an integer into a floating point number by placing a .0 at the end of the integer. Here is a little sample session.

Division works a little differently than it does on a calculator. For floating point number, division works as expected. For integers, the quotient is truncated; this is integer division. You can always make an integer into a floating point number by placing a .0 at the end of the integer. Here is a little sample session. Notice that integer division can behave unexpectedly when it encounters negative numbers.

>>>  5/3
1
>>>  5.0/3
1.6666666666666667
>>>  (-1)/(-2)
0
>>>  -1/2
-1
>>>  1/1.1414
0.87611704923777822
>>>  import math
>>>  math.pi
3.1415926535897931
>>>  1/math.pi
0.31830988618379069

3. Variables Python supports three built-in types of data:

When you create a variable, you are attaching that value to a name. You can use any variable to store any type. We can use the print function to see the values that variables hold. Experiment a bit and see. Here is a sample session; type these statements in and try a few of your own.

>>> x = 5
>>> print x
5
>>> x
5
>>> pizza = "avec anchois sil vous plait"
>>> pizza
'avec anchois sil vous plait'
>>> print pizza
avec anchois sil vous plait
>>> x = x*x
>>> print x
25

There are some interesting things to note in this little sample session. The = operator is not what it seems. You should think say "gets" instead of equals. The statement

x = x*x

means that the right-hand side (x*x) gets evaluated and gets stored into the left-hand side. The old value of x is lost forever. Assignment causes a destructive overwrite. The old value is tossed out and replaced by the new one.

4. Creating Python Programs You will begin to notice after a while that you might want to preserve pieces of Python code for repeated use. Let us begin by showing the time-honored "Hello World!" program.

If you are a LINUX user, I will assume you are familiar with a text editor such as vi. If you are in IDLE and not in the shell, just type the program in the window. Here is the code

#!/usr/bin/python
#This is my first Python program. 
print "Hello, World"

To run your program in Windows, select Run Module from the Run menu or hit F5. Python will ask you to save your program. Create a directory for your programs and save it as hello.py

To run your program in LINUX, save it as hello.py Then, at the UNIX command line, type

python hello.py

In either case, Python will reply with

Hello, World!

You will notice that the line

#This is my first Python program.
caused nothing to happen. This is a comment in the code. You may make comments on any line by using the # sign. Everything after the # is ignored. This works both in programs and in the interactive shell. Comments are a useful tool to make your code comprehensible to others and to make it comprehensible to you if you decide to open it a long time after you created it. The first line, /usr/bin/python, tells your system where the python interpreter lives. This can be a useful advanced feature for UNIX users.

5. The Core Syntax All self-respecting computing languages offer these critical features:

We will address all of these and show how to use the Python features that implement these. We can use the interactive shell as a laboratory, before we place things in programs.

5.1 Forking Python uses the if statement as the means of implenting conditional execution. The general form of an if statement is as follows

if boolean:  #<- Notice the colon!
	statement1  ##use the tab key to indent in the shell or in a file.
	statement2
	.
	.
	. 

	lastStatement
The indented statements after the if are said to be the block of code attached to the if. If the boolean expression after the if evaluates as true, the code in the block is carried out. Otherwise, it is skipped. Here is an interactive example.
>>>  x = 0
>>>  y = 5
>>>  z = 3
>>>  if(x*y == 0):
	print "at least one variable is zero"
at least one variable is zero
>>>  if(y*z == 0):
	print "at least one of the variables is zero"
>>> 
Notice how Python did not respond to the second if statement, becuse the value y*z is nonzero! It replies mutely with a new prompt. Also observe that we check equality between variables with ==; this is the check-for-equality operator. Remember, = is assignment; it is read "gets". Confusion between these is often a cause for bugs in programs. Lastly, notice that Python knows the block is over when the indentation stops.

Now let us enter code in a file named ifTest.py We will learn some addtional features here

#!/usr/bin/python
age = input("Enter your age:  ")
if age < 18:
	print "You cannot drink or vote"
elif age < 21:
	print "You cannot drink, but you can vote."
else:
	print "Do not drink and vote."

The first line creates a variable called age. It puts the prompt Enter your age: to the screen and waits for the user to type in an integer. Execute this program three times and use the ages 34, 22 and 8. Here is the output you will see.

>>>  ================================ RESTART
>>>  ================================
>>>  
Enter your age:  34
Do not drink and vote.
>>>  ================================ RESTART
>>>  ================================
>>>  
Enter your age:  19
You cannot drink, but you can vote.
>>>  ================================ RESTART
>>>  ================================
>>>  
Enter your age:  8
You cannot drink or vote
>>>  

If you are using LINUX, you will not see the interactive prompt. This statement includes two new elements, elif and else. You can fork as many ways as you like by using an if-elif cascade. Here is the general format

if boolean1:
	#do this is boolean 1 is true and drop to the bottom
elif boolean2:
	#do this is boolean 2 is true and drop to the bottom
.
.
.
else:
	#this is the default.  Use it to report errors.
#The end of the cascade

In an if-elif cascade, you will execute at most one of the blocks of code. To be safe, always use a default. This could report an error for some illegal state of your program. Here is a somewhat contrived but simple example.

#!/usr/bin/python
age = input("Enter your age:  ")
if age < 18:
	print "You cannot drink or vote"
elif age < 21:
	print "You cannot drink, but you can vote."
elif age >= 21:
	print "Do not drink and vote."
else:
	print "Illegal age: no negative integers allowed.  #error report

5.2 Looping Now we shall turn to the problem of doing repetitive tasks. There are two constructs in the language to handle this: while and for. The syntax is pleasingly simlilar to that of if

The syntax for while is

while boolean:  #Notice the colon at the end!  Just like if.
	statement 1
	statement 2
	.
	.

	statement n

Here is a simple example.

n = 10
while n >= 0:
	print n
	n = n - 1
print "Blastoff!"

At the risk of being tedious, let us step through the process. The variable n holds the value 10. Since n >=0, we enter the while loop and 10 is put to the screen. The statement n = n-1 lowers the value of n to 9. The boolean n >= 10 is true so the statements in the loops's block execute again. This keeps happening until n is 0. At this time, we leave the loop and print "Blastoff!" to the screen. The output will look like this

10
9
8
7
6
5
4
3
2
1
0
Blastoff!

Now let's look at for. To fully appreciate it, we have to know about lists. Here are two lists you will come to appreciate. Let's show some examples at the interactive shell

>>> range(1,10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(0,10,2)
[2, 4, 6, 8, 10]

In general, the list range(a,b) starts at a and ends before b. Each new element is 1 larger than its predecessor. The list range(a,b,skip) counts starting at a, stopping before b in increments of skip. Make some of the arguments you pass to range negative and see what happens!

You can make lists of any types of objects; you can fill these by listing explicitly. For example

shopping = ["milk", "champaign", "caviar", "strip steaks"]
is a list of strings. You can have heterogeneous lists too like this one
garbage = [5.3, 44, "scissors", "rock", 223]

Extracting elements of a list is done with the [] operator. Here is an example interactive sesssion; note the comments annotating the action.

>>> garbage = [5.3, 44, "scissors", "rock", 223]
>>> garbage[0]		#print the 0th element of the list garbage
5.2999999999999998
>>> print garbage[1]  # print the first. remember we start counting at 0
44
>>> for k in garbage:	#iterate through the list
...     print k					#print each element in turn
...
5.3
44
scissors
rock
223
>>> print garbage[2:]  #print all elements from 2nd to end
['scissors', 'rock', 223]
>>> print garbage[2:4] #print all elements starting at second
								#before the 4th.
['scissors', 'rock']
>>> print garbage[:2]  #print all elements before the 2nd.
[5.2999999999999998, 44]
>>> len(garbage)       #print the lenght of the list garbage.
5

Isn't it interesting that the lists garbage[:2] and garbage[2:] are disjoint? This can be very convenient.

Now, after this digression on lists, let's get back to the main point. You can step through a list and execute code on each item by using the construct

for list
	statement1
	statement2

	.
	.
	.
	statementn

The for loop takes as input a list and performs the block of code attached to it for each element of the list.

5.3 Modularization Large programs can become unwieldly to maintain and debug. Python provides two methods of modularizing programs. We will deal with the "inner" layer here, Python functions. Here is the syntax for declaring a function.

def f(arg0, arg1, arg2, ... argn):
	statement1
	statement2

	.
	.
	. 
	statementn

The statements attached to the function f are called the body of f. The items arg1 through argn are called the arguments of the function. They are the pieces of information passed to a function that are needed for the function to do its job. Sometimes, a function will have no arguments.

Python functios are a little different from mathematical functions. Just as mathmatical functions do, they have one or more inputs. However, they may have no outputs. They may also have side-effects, which are things they do other than passing or receiving information.

Let's get concrete with some sample code. Enter this code in.

#program helloFunction.py
#Demonstration of a function that prints to the screen
def hello():
	print "Hello, there!"
hello()
If you run this code, it will put the words Hello, there! to the screen. This function takes no inputs; it simply executes its block of code. It makes no outputs. The printing to the screen is a side-effect of the function hello().

The line

def hello():
is called the function header for hello.

Let us make this function fancier by giving it an input. The block attached to the function header is called the implementation of the function. It is marked off by indentation. Finally, the line

hello()
is called a call to the function hello.
#!/usr/bin/python
#program helloName.py
#Puts a greeting to the screen with a specified name

def hello(x)
	print "Hello, ", x, "!"
hello("Morrison")
hello("Teague")
q = "Donita Robinson"
hello(q)

The output of this program will be

Hello, Morrison!
Hello, Teague!
Hello, Donita Robinson!

Notice that this function returns no output; it accepts input and produces side-effects based on the input. Now let us see an example of a function with output.

#!/usr/bin/python
def greet(x):
	return "Hello, " + str(x) + "!"
def printGreeting(x):
	print greet(x)
greet("Mr. Yoda Ears")

The function greet accepts a string x (puportedly a name), and returns the string containing a greeting to x. You will notice the use of the unfamiliar function str; this converts whatever is given it to a string. The function printGreeting accepts a string and prints the greeting for that string. Notice that it returns nothing. The keyword return is used to send output back to whomever requested it. This example here shows that functions can call each other.

6. Exended Integer Calculations with Python Python provides a friendly environment in which we can do calculations with extended-precision integers. It automatically promotes any integer to an extended-precision integer where necessary. Let us show a simple example here

def factorial(n):
	p = 1
	if(n < 0):
		print "Domain error in function factorial"
		return -1; ##use an absurd value you can check with an if statement
	else:
		for k in range(1, n + 1):
			p = p*k
	return p
print factorial(5)
print factorial(10)
print factorial(100)
print factorial(-5)

This produces the output

120
3628800
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Domain error in function factorial
-1

You will notice that Python is using extended-precision arithmetic to compute 100!

Let us denote by b(n,k) the number of subsets of size k in a set of size n; this is the binomial coefficient n choose k. Recall that it can be computed by

b(n,k) = n!/(k!(n-k)!)

We, however, will be smarter than that. We perform the calculation with a zigzag technique that does not allow the denominator to become too huge. This saves memory and minimizes the chance of a type overflow, or of running out of memory.

def binomial(n,k):
	p = 1
	for j in range(0,k):
		p = p*(n - j)/(j + 1)
	return p
Functions in Python can call themselves; this is called recursion. We can use the identities
b(n,n)=b(n,0) = 1, n >=0
b(n,k) = b(n-1,k) + b(n-1,k-1), n >=1, 0 ≤ k ≤ n
b(n,k) = 0, k < 0, k > n
to compute binomial coefficents. Here is a Python function that calls itself to compute the binomial coefficients.
def pascal(n, k):
	if n < 0 or k < 0 or n > k:
		return 0
	if k == 0 or k == n:
		return 1
	return pascal(n-1, k-1) + pascal(n - 1, k)

Notice how in each call, the function moves closer to a "base case" that causes it to return and resolve. If a recursive function does not do this, you may experience a Stack Overflow message. The function calls keep piling up in memory and overflow the space your program was allotted by the operating system.

Recursion allows us to compute Stirling number of the second kind. We define S(n,k) to be the number of ways to partition a set of size n into k nonvoid subsets provided that n and k are nonnegative. . We define S(0,0) = 1; clearly, if n is positive, S(n,0) = 0. These number have a recursive representation. Imagine you have a set of n elements; let us single out one element and label it as being element 1. Suppose k is a positive integer and k ≤ n. Take all the elements except 1 and partition them into k subsets; there are S(n-1, k) ways to do that. Having done that there are k ways to pick a subset to put the 1 into. The total number of ways of doing this is k*S(n-1,k). This counts all paritions of the n elements into k subsets where 1 is not alone. Now let's count all the partitions where 1 is alone. First, isolate 1 all by itself. Then partition the remaining n-1 items into k - 1 subsets. This can be done S(n-1, k -1) ways. We may now conclude that

S(n,k)= k*S(n-1,k) + S(n-1, k-1).

Here are some "obvious" things. First, S(n,k) = 0 if k < 0; you cannot partition a nonvoid set into zero subsets. Since there are only n elements in the set to go around, S(n,k)=0 if k > n. Also we have S(n,n) = 1 and S(n,1) = 1 for n ≥ 1. We are ready to compute these numbers with recursion by using the function

def stirling(n,k):
    if n == 0 or k < 0 or k > n:
	        return 0;
	if k == n or k == 1:
	       return 1
	else:
	       return k*stirling(n-1,k) + stirling(n-1,k-1)

You can think of many interesting experiments in which you can compute with extended-precision numbers!

7. File this away Here we do a short introduction to reading from and writing to files in Python. You can save results of calculations from things like Euler's rule in a file and open them with Graphical Analysis to visualize them.

Here is an example of code that writes to a file

f = open("screech.txt", 'w')  ##opens file screech.txt for writing
for k in range(1,21):
	for j in range (1, 5)
		f.write(str(k**j)
		f.write("\t")    
	f.write("\n")

If you are using UNIX, you may also write to a file by redirecting standard output using the > operator. Here is an example of how we direct the output of foo.py into the file bar.txt

foo.py > bar.txt

Learning Resources There is a website for Python. It is brimming with tutorials and learning materials for people with all levels of programming proficiency.