Python is *expressive*! It's a high level, general purpose language which offers a lot of flexibility in how you can use it.

Python is *availible*! It's a widely used, free language that runs on many different platforms.

Python is *extensible*! There are many modules are availible for solving all kinds of problems from fetching data from web servers, writing games, doing large numerical computations, and so on...

Python is *interpreted*! Though this is not an absolute benefit - for us, this means writing code and running is more closely coupled, which is great for exploring new problems and getting feedback from your code as you write it.

We'll start out by having Python say hello to us. To do this, we'll write

In [1]:

```
print "Hello World"
```

Great! That was easy and things are looking good!

Now let's doing some number crunching, using Python as our calculator

In [2]:

```
1032 + 431
```

Out[2]:

In [3]:

```
(1232 + 3.0) * 43
```

Out[3]:

In [4]:

```
2.0 * (1032.0 + 3.0) / (3.0 + 4.0*7.1)
```

Out[4]:

In [5]:

```
1102 % 7
```

Out[5]:

If we want to compare two numbers, we can just write (almost) what we'd expect

In [6]:

```
2 ** 8 >= 200
```

Out[6]:

In [7]:

```
346 % 2 == 0
```

Out[7]:

In [8]:

```
P = 800.0
r = 0.01
t = 2.0
print P*(1 + r)**t
```

In [35]:

```
s = "The String Called s!"
t = "The String Called t!"
print s
print s + " " + t
print len(s)
```

In [36]:

```
x = True
y = False
print x
print x and y
print x or y
print not x
print not not x
```

I can also do things like reassign a variable in order to increment it.

In [11]:

```
x = 10
x = x + 1
print x
```

Or if I prefer, I can use the short-hand for it:

In [37]:

```
x = 10
x += 1
print x
```

Translate the following expression into code: $\frac{1.3/1.2 + 4.3 \times 2.0}{1.5 - 2.3}$

Check if 4431 and 7523 are equal mod 7.

Define pi using the approximation $\frac{355}{113}$. Use it to compute the circumference and area of a circle of radius 5. (There's a subtle error which can occur in this problem! Try printing out pi after defining it. Do you get an unexpected answer? What do you think happened?)

Now, suppose I want to do something like compute the minimum of two numbers or compute the absolute value of two numbers. How would I do something like this? Well, we know one definition for these is:

$$ \min(a, b) = \begin{cases} a & \mbox{if } a < b \\ b & \mbox{if } a > b \end{cases} $$$$ | a | = \begin{cases} a & \mbox{if } a > 0 \\ -a & \mbox{if } a < 0 \\ 0 & \mbox{if } a = 0 \end{cases} $$How would we turn this into code? Let's start with just the decision making itself. We can do this by introducing conditional statements:

In [12]:

```
x = 30
y = 20
if x < y:
print x
else:
print y
```

If there are multiple or even many choices, then we can write something like:

In [13]:

```
day = 4
if day == 0:
print "Monday"
elif day == 1:
print "Tuesday"
elif day == 2:
print "Wednesday"
elif day == 3:
print "Thursday"
elif day == 4:
print "Friday"
elif day == 5:
print "Saturday"
elif day == 6:
print "Sunday"
else:
print "...that's not even a real day..."
```

In [14]:

```
def min(x, y):
if x < y:
return x
else:
return y
print min(3, 5)
print min(9, 4)
print min(min(5, 2), 3) # I can even plug a result into another computation!
```

One of the most important consequences of this is approach us, I don't care how a function is implemented. *(Assuming it's implemented correctly and maybe whether it's efficient or not! But, most importantly, I don't have to worry about correctness!)*

For example, if one of my friends comes along and decides to implements a function slightly (or not so slightly) differently it shouldn't affect the way I use the function!

In [30]:

```
# my implementation of double
def double(x):
return 2 * x
print double(7)
# my friend's implementation of double
def double(x):
return x + x
print double(7)
```

In [31]:

```
def add_three(x, y, z):
return x + y + z
```

Or even a kind of silly function like:

In [33]:

```
def really_random_number():
return 3
```

In [34]:

```
def show_a_minus_b(a, b):
return a - b
print show_a_minus_b(a=2, b=1)
print show_a_minus_b(b=7, a=2)
```

Write a short function which decides if an integer is even.

Fill the details for the absolute value function.

Write a function which squares a number and then use it to write a function which takes three integers and returns the sum of their squares.

Write a function which computes the factorial of an integer.

As you may imagine, we don't always have to do all the hard work and write everything ourselves. In fact, a few of the functions we've define such as min and abs are built in to Python. So, how can we use an externally defined function or definition? Let's add some new functions to our "calculator" from earlier from Python's math module.

In [18]:

```
from math import sin, cos, pi
print pi
print sin(2.1*pi)
```

*namespace*.

In [19]:

```
import math
print math.pi
print math.sin(1.0)
```

In [20]:

```
n = 1
while n <= 10:
print n*n
n += 1 # Short hand for x = x + 1
```

Similarly, I may try to add the first 100 integers.

In [21]:

```
n = 1
total = 0
while n <= 100:
total += n
n += 1
print total
```

Another very useful, more general way of doing these kinds of things is by using iterators. One of the simplest iterators abstracts away the process of looping over a range of numbers.

We can rewrite the computations above using iterators as follows:

In [1]:

```
for n in range(1, 11): # [1, 11) <---
print n*n
```

In [2]:

```
total = 0
for n in range(1, 101):
total += n
print total
```

*break* statement to do this.

In [4]:

```
n = 0
print 'start!'
while True:
print 'before!'
if n == 3:
break
print 'after!'
n += 1
print 'done!'
```

Write a function which adds up the squares of the first $n$ odd integers.

Write a function which prints the natural numbers less than $n$ which are divisible by 3, divisible by 5 but not divisible by 10.

Write a program which prints out an 16 x 16 "chess board" which indicates a black square with a 'B' and a white square with a 'W'.

Print out the first ten Fibonacci numbers.

Try reimplementing the factorial function using either a while loop or an iterator. Which do you think is better? Which do you think is easier to understand?

As you develop small pieces of code, you'll want to check if they are correct. For very simple code this isn't usually a problem. But, even in those cases, there can be a danger of "one-off errors" or not predicating a strange type error. In those cases, it can be useful to write some code to test the functions you're writing. One of the simplest ways to do this is by using the assert command.

In [17]:

```
def sum_first_n(n):
k = 0
s = 0
while k <= n:
s += k
k += 1
return s
```

In [18]:

```
def test_it():
assert sum_first_n(0) == 0
assert sum_first_n(1) == 1
assert sum_first_n(2) == 3
test_it()
```

One question which came up was how to document or comment code. This can be done using the # symbol:

In [2]:

```
# assigning my variables
x = 4
y = 6
# checking which is smaller
x < y
```

Out[2]:

In [3]:

```
min(4, 6) # speaks for itself, so comment shouldn't be here.
```

Out[3]:

Another question which came up regarding the chessboard problem was how to print without creating a new line and how to print a blank line. This can be done as follows:

In [4]:

```
# these don't print newlines!
print 'W',
print 'B',
# a blank print will generate a line break
print
```

One last nice syntactic feature is doing multi-assignment:

In [6]:

```
a, b = 1, 1
for n in range(10):
a, b = b, a+b # multi-assignment
```

In [8]:

```
a, b = 1, 1
for n in range(10):
t = a+b
a = b
b = t
```