(contents)

Python is a 5th generation language created by Guido van Rossum in the 1990's. Python became popular for scientific computing around 2000

- An interpreted language that was free, more flexible than Matlab, and more fun to write than C and Fortran.
- A large collection of modules for various tasks
- A useful set of built-in data types (lists, dicts, strings)
- Being able to easily return multiple results from a function (unlike C)
- A well-documented API allowing easy integration with C and Fortran code.

At that time, however, python lacked the right powertools for working with matrices. That was fixed with the release of numpy in 2005, which unified the competing `Numeric`

and upstart `numarray`

modules. Since then, python has continued to develop, with object orientation, functional programing, closures, generators, unicode, coroutines.

Currently, two versions of python are in wide use: Python2.7 and Python3 From the beginners standpoint in english-speaking countries, the differences are minor. We'll use Python2.7 mostly.

- Python home page
- Modules
- SciPy suite
- NumPy for basic matrix (array) tools.
- Matplotlib for standard plotting (curves, images, ...)

- Tutorials
- A nice short tutorial.
- The official Beginner's guide
- For a good introductory book with class-relevance, see A primer on scientific programming with Python by Hans Petter Langtangen.

- Distributions and ways to get python
- Company Enthought's Canopy distribution of python and it's modules is freely available for academic use.
- Company Continuum Analytics's Anaconda distribution is also very popular (maybe more-so).
- You can also experiment with python (and other languages) using a web notebook

To get a python shell running int the terminal, use the command

`$ python`

(I'm using the "$" symbol to represent the regular shell prompt -- don't type it, just the "python")

Like any command-line shell, python's interpreter evaluates instructions you enter at the `>>>`

prompt. In this case, the instructions expressed in the python language. Type the following commands into the python prompt and observe the results.

First, python does simple arithmetic like a calculator...

```
>>> 2+3
>>> 2*3
>>> 2**3
>>> 7^2
```

Note that `**`

is used for exponentiation in python, while `^`

is used for bit-wise negation (a boolean operation -- if you don't know what it is, do not worry, you do not need to know).

Python uses variables to store things in memory.

```
>>> x = 13
>>> y = x - 5
>>> print y
```

Here, we have also introduced the command `print`

, which is one of about 30 reserved words that makes up the python language. Really, it's true, the whole language has only 30 words! Here is a slightly more complicated example of how `print`

can be used with strings and inputs.

```
>>> print "Hello, World"
>>> name = raw_input("What is your name? ")
>>> print "Hello, %s. Nice to meet you."%name
```

In the two cases above, `x`

, `y`

, and `name`

are "variables". Variables in python are "dynamically typed", which means they can store many different kinds of things, and you just have to remember what kind of thing is in each one as you program. Python has a few basic variable types built in, and a simple class system for creating more of your own.

One of the primary features of applied mathematics that differs from pure mathematics is that numbers are seldom pure abstractions. Instead, they usually have attributes, like **units**, which inform their use and interpretation. (If one number measures temperature in units of degrees Farenheit and another number measures distance in units of miles, we know it makes no sense to add these numbers together, even though there is no *mathematical* difficulty with the operation.)

Another important attribute of numbers that comes into play in programming is their **type**, or *how they are stored in computer memory*. There are many different types we could use for numbers, and these types effect how some algebraic operations work.

The most basic type for a number in python is an `int`

, which is short for *integer*. An `int`

is an integer, stored in base-2.

```
>>> x = 3
>>> type(x)
```

Numbers stored as `int`

's can be added, subtracted, multiplied, and exponentiated. And since they are stored in binary format, we can also perform elementary boolean logic operations of and (`&`

), or (`|`

), and not (`~`

) on them. For each of the calculations, try to predict what the answer will be before you do it.

```
>>> x = 2
>>> y = 5
>>> x + y
>>> - x
>>> x - y
>>> x * y
>>> x ** y
>>> x ^ y
>>> x | y
>>> x & y
>>> ~ x
```

Note that `**`

is used to represent exponentiation in python, fortran, and some other languages. What logical operation does `^`

represent?

In addition to these operations, integers can be divided, but as you learned long ago, integer division is a little more complicated, involving quotients and remainders. Python can calculate both of these; `x/y`

returns the quotient, while the *modulus* operation `x%y`

returns the remainder.

```
>>> x, y = 13, 5
>>> x / y
>>> x % y
```

We can also compare integers using infix notation of common ordering relations; equality `==`

, less than `<`

, less than or equal to `<=`

, greater than `>`

, greater than or equal to `>=`

, unequal `!=`

.

```
>>> x == y
>>> x != y
>>> x < y
>>> x >= y
```

The second type we commonly use for numbers is the `float`

type which is short for *floating point format*, what you probably think of as "decimal numbers". Floating point numbers are typically stored in IEEE format with a sign bit (s), a mantissa (m), and an exponent (e) to represent the number $(-1{)}^{s}\times m\times {2}^{e}$. All your standard calulator operations work like you would expect with floating-point numbers. Logic operations **DO NOT** work (or even make sense) for floats.

```
>>> x = 0.2
>>> y = 0.5
>>> x + y
>>> - x
>>> x - y
>>> x * y
>>> x / y
>>> x ** y
>>> # the following logic operations will not work, and will raise an error
>>> x ^ y
>>> x | y
>>> x & y
>>> ~ x
```

Testing equality is a little trickier with floats because two number that should be equal may differ because of round-off error -- only the largest 16 decimal places of a number can be stored. Because of this, we usually test if two numbers are "close enough" to be considered equal, rather than testing equality directly.

```
>>> x = (5 ** .5 + 1)/2
>>> y = 2/(5 ** .5 - 1)
>>> x/y
>>> x == y
>>> abs(x-y) < 1e-14
>>> abs(x-y)
```

Python also has complex-numbers built-in, which can be very useful for simple 2-d graphics.

```
>>> x = 1j
>>> x * x
>>> (2-3j) * (2+3j)
>>> a = 2.+4j
>>> b = 1/a
>>> (a, b, a*b)
>>> b.real
>>> b.imag
```

Just like in regular algebra, Python assumes certain operation precedence rules that can be overridden using parentheses.

```
>>> 2 + (3 * 5)
>>> (2 + 3) * 5
>>> 2 + 3 * 5
```

Remember, integers **are different from** floating-point numbers!

```
>>> u = 3
>>> v = 3.
>>> type(u)
>>> type(v)
>>> u/2
>>> v/2
```

Python will "escalate" the type of numbers in a calculation to float (or complex) once they are introduced, but sometimes you have to make that explicit to the interpreter. Adding a decimal point to a number is an easy way to let the interpreter know that you want the answer to be a float rather than an integer. The other way is to explicitly cast the numbers.

```
>>> 1/5
>>> 1./5
>>> float(1)/5
```

Be aware that `python3`

changes how these numerical operations deal with number types. However, the general issues still exist in statically typed languages like C++ and Fortran.

Python also has more complicated data-types built-in.

Python has strings used to store words and letters.

`>>> s = "hello World" >>> print s`

Python has lists for sequences of objects

`>>> mylist = range(7) >>> mylist >>> mylist[0] >>> mylist[1] >>> mylist[-1] >>> mylist[1:3]`

Python has dictionaries (called

`dict`

's) for pairing items using a hash algorithm.`>>> mydict = dict() >>> mydict['red'] = 'apple' >>> mydict['blue'] = 'sky' >>> mydict['red']`

You can also format how things are output using the

`print`

command.`>>> print "u=%d is an integer, v=%f is a float"%(u,v)`

`print`

works allot like`printf`

in C.`print`

is especially useful because it always outputs, even when you are not interactively using the interpretter.

In most modern computer languages, functions are used regularly. A function in python is a piece of code that takes one or more arguments, and returns one or more results. Functions begin with the keyword `def`

and usually finish with the keyword `return`

followed by whichever variables you want to return. The body of each function must be indented 4 spaces in from the beginning of the line. The first line of a function must always end with a colon `:`

.

The basic format of a function definition is

```
def ...( .... ) :
...
...
return ...
```

Try the following example functions.

```
>>> def F2C(F):
>>> C = (5 * F - 160)/9.
>>> return C
>>>
>>> def convertF2C():
>>> temp = raw_input("What_is the temperature (in degrees Farenheit)? ")
>>> tempInCelcius = F2C(temp)
>>> print " That would be %.1f degrees Celcius"%tempInCelcius
>>> return
>>>
>>> convertF2C()
```

There's allot here to absorb. There are two functions, each defined using the `def`

keyword. The lines with `def`

end in a colon. The bodies of each function are delimited using indentation. The python language uses indentation to indicate which parts of a program are inside other parts -- in this case, the indentation indicates which lines of code are inside which functions. Unlike some other languages like C and Perl, the indentation is **not optional** -- indentation is required. Fortunately, most editors help you stay consistent with automatic indentation.

The variables created inside a function can not be seen by other code and functions -- only the things that are returned can be used. The domains where a name can be used in a language are called its *scope*. In python, the general scoping rule is that variables created inside functions are forgotten as soon as the function ends unless they are returned by the function. For example, in the functions above, the function `F2C`

can not see or use the variable `temp`

, while the function `convertF2C`

can ot see or use the variable `C`

.

Being able to do simple calculations is good, but often we need to change a calculation to match the situation at hand. That's where **conditionals** come in. A conditional is the computer-language equivalent of a logical implication, an "IF .... THEN ... " statement. In fact, that's exactly how many languages implement conditionals. Here is an example of a python conditional inside a function.

```
>>> def isodd(n):
>>> if n > 0:
>>> print n, " is a positive number"
>>> else:
>>> print n, " is not a positive number"
>>> return
```

The conditional begins with `if`

, is follows by a logical expression that evaluates to either `True`

or `False`

, and ends in a colon. If the logical expression is true, then the interpretter executes the indented code making up the conditional's body. Otherwise, the code in `else`

clause is executed. The `else`

is optional -- not all if-statements have an `else`

. Sometime conditionals also use `elif`

closes to test additional situations.

```
>>> def tellsign(n):
>>> if n > 0:
>>> print n, " is a positive number"
>>> elif n < 0:
>>> print n, " is a negative number"
>>> else:
>>> print n, " is zero"
>>> return
```

The next most important concept in programming is the Loop. A loop is a piece of code that you want to execute repeatedly in some form or other. Inside the computer, loops are executed by combining conditionals with `goto`

statements telling the program to change it's execution location. In a structured language like python, loops are described using the `while`

or `for`

keywords.

```
>>> t = 0.
>>> print "A simple temperature conversion table"
>>> print "-------------------------------------"
>>> while t < 100:
>>> print t, F2C(t)
>>> t = t - 5
```

Like an `if`

statement, the `while`

loop has a boolean expression, ends in a colon, and has an indented body.

A `for`

loop is a little fancier and more powerful.

```
>>> for T in range(10):
>>> print T, F2C(T)
>>>
>>> for T in range(-10,100,5):
>>> print T, F2C(T)
```

The `range`

function returns a list, including the first entry but never the last, incrementing by 1 by default.

Together with variables, loops and conditionals are the core components that make a computer language Turing-complete -- any computer program written in a classical language can be translated and computed in any language with loops and conditionals. On the other hand, because of the power of these language constructions, there is no universally applicable way to verify the correctness of your programs.

```
>>> def gcd(x, y):
>>> if x > y:
>>> return gcd(y, x)
>>> if x < 0:
>>> return gcd(-x, y)
>>> while y >= x:
>>> y = y - x
>>> if y == 0:
>>> return x
>>> return gcd(y, x)
```

To test if our function works, we can try it with a few examples that we already know the answers to.

```
>>> gcd(2,3)
>>> gcd(4,6)
>>> gcd(6,4)
>>> gcd(-6,4)
>>> gcd(-6,-4)
>>> gcd(30,100)
```

You can use Visualize python to follow how the program works -- once you learn to read code, you should be able to do this all in your head.

Find a better implementation of the

`gcd`

algorithm for calculating greatest common divisors. Your program may be better because it is shorter, faster, or more readable.Estimate the fraction of pairs of positive integers are relatively prime to each other using your

`gcd`

function.Write a function to calculate the least common multiple of two positive integers.