Notes for first lecture

  • What is python?
  • Distros, notebooks
  • import
  • variables, functions
  • lists, tuples, arrays, strings

What is python?

Python is an interpreted language

That means it responds to things you type in and it is waiting for you to type things. It excecutes instructions on the CPU based on what you type.

Interpreted languages are usually slower than compiled languages.

A compiled language produces CPU runable code from a series of instructions. You then run the code. Compilers are designed to make efficient code.

However, python does compile its functions. One a function is loaded into python, a compiled version can be made that then can be run later on.

Python is still usually slower than something compiled like C, C++ or Fortran.

If you have a computationally intensive task, you could link from python to a library compiled code that is originally written in C or another language.

Why are we using python?

  • It's free, multiplatform and maintained
  • It has a good and large scienfic user base. Lots of nice tutorials. Many questions answered on-line. Lots of example code that can be easily found via a search.
  • There are many useful packages developped for scientific applications. e.g., astropy, trackpy, Scikit-Learn, Tensorflow

If you are an engineer or a biologist you might wind up using matlab (which is not free) instead of python. Many matlab-like routines have been ported into python.

python distros

You need to have a python distribution that contains packages numpy, matplotlib.

I like to use jupyter notebooks as you can easily rerun code, embed figures and use markdown with pretty latex equations.

I encourage you download a python distribution, like the free ones available as anaconda or canopy that comes with notebooks.

launching python

I usually launch jupyter notebooks from a command line but you can also use the ap that comes with various distributions.

Jupyter notebooks

Why work in a browswer? The data you are working on need not be on your computer. The code that you run need not be run on your computer. The code you run need not be developed for every type of operating system if you run your code on special computers that are not your computer.

What needs to be on your computer? A way for you to look at the code output.

Browsers are optmimized to display things efficiently for your eyes.

Jupyter notebooks are good for running and rerunning code as you develop it. They can be used to keep a record of your projects. You can embed your equations and figures in the project.

Can you collaborate in a jupyter notebook? Not yet: There are some non-free platforms under development. Maybe by next year it might become possible to simultaneously edit a notebook with a friend on-line (on a free platform).

For large projects you need to write subroutines in separate files. You could then load them into a notebook to run.

types of boxes in a notebook

code and markdown.

Markdown

Markdown lets you make nice TeX equations!

$x=1$

$$ \sum_{x=1}^\infty z^\alpha $$

Lists

  • apples
  • oranges
  • frogs

Html bold!

nice code:
    more  nice code

variables:

  • setting a variable to be a number
  • printing
  • +=
In [1]:
# showing some variable assignment + manipulation
x=1
x=x+1
print(x)
x+=1
print(x)
2
3
In [2]:
x
Out[2]:
3
In [ ]:
?x

Differences between python 2.x and 3.x

The most irritating difference is in the print function.

Thankfully many packages have been upgraded to 3.x

In [3]:
sin(3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-2b5fc2868c51> in <module>
----> 1 sin(3)

NameError: name 'sin' is not defined

numpy (numerical python)

importing a package

In [2]:
# showing how to import numpy
import numpy as np
x=1.0
np.sin(x)
Out[2]:
0.8414709848078965

$\pi$

In [5]:
np.pi #pi!
Out[5]:
3.141592653589793
In [6]:
# An example of importing a function 
from numpy import exp 
In [7]:
# we don't need to use np.exp()
exp(x)
Out[7]:
2.718281828459045

importing another package

In [8]:
import os  # operating system
os.getcwd()
Out[8]:
'/Users/aquillen/Desktop/phy256cmpphys/pylab/lectures'

variables

In [9]:
# multiple variables at once!
x=1
y=2
x,y = y,x
x,y  # this is a tuple 
Out[9]:
(2, 1)

define a function

In [10]:
# define a simple function
def f(x):
    y = (x+7)**2
    return y
In [11]:
# print for python 3.x uses ()
print(f(8.0))
225.0
In [13]:
# functions can take more than one argument and 
# can return more than one thing as a tuple
def g(x,y):
    if (x >0):
        return 0,x
    else:
        return 1,y
    
a,b = g(1,2)
print('g(1,2)=',a,b)
a,b = g(-1,2)
print('g(-1,2)=',a,b)
g(1,2)= 0 1
g(-1,2)= 1 2

notice the indents

indents can be 4 spaces or a tab but you can't mix the types of indents

Indents are a pain.

In [14]:
# lets screw up some indents
def h(x):
return x**1.5
  File "<ipython-input-14-2c7751c58180>", line 3
    return x**1.5
    ^
IndentationError: expected an indented block
In [15]:
# lets screw up some indents
def h(x):
 return x**1.5

h(2)  # this works but the red tells you there is a problem
Out[15]:
2.8284271247461903

indents affect the code

In [16]:
# twofunctions that are identical except for indents
def h1():
    ssum = 0 
    for i in range(3):
        ssum += i;
        for j in range(3):
            ssum +=j
    print(ssum)
            
def h2():
    ssum = 0
    for i in range(3):
        ssum += i;
    for j in range(3):
        ssum += j;
    print(ssum)
    
        
h1() # these do not give the same answer
h2()
12
6

why did I use ssum instead of sum?

In [ ]:
sum = 1   # do not run this!  sum is green and that means it has another use
lambda    # 
np =3   # don't run this if you want to use numpy as np!
str   # don't run this if you want to use str to convert something to a string

strings

In [17]:
# examples of string manipulation
str1 = 'Pan'
str2 = '_is_a_moon'
zzz = str1 + str2
print(zzz)
zzz[0]  # indexing a string
n = len(zzz)  #length of string or array or list
print(n)
Pan_is_a_moon
13

single quotes vs double quotes for strings

In [60]:
str1 = "Pan" 
In [61]:
str3="Pan'   
  File "<ipython-input-61-0197142baa33>", line 1
    str3="Pan'
                 ^
SyntaxError: EOL while scanning string literal

you can use single quotes or double quotes for string constants but you need to start and stop the string with the same symbol

indexing a string (an array of characters)

In [18]:
zzz[14]   # outside of allocated memory
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-18-d240a8f97730> in <module>
----> 1 zzz[14]   # outside of allocated memory

IndexError: string index out of range
In [19]:
zzz[-1]   # last thing in list
Out[19]:
'n'
In [20]:
zzz[-4:]  # last four things in the list
Out[20]:
'moon'
In [21]:
zzz[0:3]  # first 3 things in the list
Out[21]:
'Pan'

indexing goes from 0 to n-1 where n is the length

range is an iterator

In [22]:
zzz = 'Pan_is_a_moon'
n = len(zzz)  # length of the string
for i in range(n):
    print(i,zzz[i])   # useful for making for loops!
    
0 P
1 a
2 n
3 _
4 i
5 s
6 _
7 a
8 _
9 m
10 o
11 o
12 n
In [ ]:
# notice that above the printout started with index 0

lists use []

In [23]:
# lists
mylist = [1,2,3,4]
for i in mylist:
    print(i)
1
2
3
4

tuples use ()

In [24]:
atup = ('a', 'bc', 'cd', 4)  # a tuple
for i in atup:
    print (i)
a
bc
cd
4

iterating over a list

In [25]:
mylist = ['A', 'b', 1, '17',17.5]
for i in mylist:
    print(type(i))
<class 'str'>
<class 'str'>
<class 'int'>
<class 'str'>
<class 'float'>

an array

In [26]:
x = np.array([1.0,2,3,4])  # an array is different than a list
x[-1]  # the last object in the array
Out[26]:
4.0
In [27]:
y=[6,7,8,9]   
print(y)

y[2] = [1,2]  # if y is a list you can set an element into to become another list

## Question:  what is going to happen?
print(y)
[6, 7, 8, 9]
[6, 7, [1, 2], 9]
In [28]:
x = np.array([1.0,2,3,4])  # an array is different than a list

## Question: what is going to happen?
x[2] = [1,2]  

# Answer: you cannot do this if x is an array rather than a list (you get an error)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
TypeError: float() argument must be a string or a number, not 'list'

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
<ipython-input-28-8d31e8065ac9> in <module>
      1 x = np.array([1.0,2,3,4])  # an array is different than a list
----> 2 x[2] = [1,2]  # you cannot do this if x is an array rather than a list

ValueError: setting an array element with a sequence.
In [29]:
## Question:  what will happen?
x[2]='a'  
# Answer: you cannot do this if x is an array (you get an error)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-29-ecf3d288781c> in <module>
----> 1 x[2]='a'  # you cannot do this if x is an array

ValueError: could not convert string to float: 'a'

copying arrays

In [30]:
x = np.array([1.0,2,3,4]) 
print(x)
[1. 2. 3. 4.]
In [31]:
y=x  # y just points to the x array
print(y)
[1. 2. 3. 4.]
In [32]:
x[2]=10.0  
## Question: what will happen?
print(y)
# Answer: if you change an element of x, then that element in y will also change
[ 1.  2. 10.  4.]
In [33]:
x = np.array([1.0,2,3,4]) 
z = np.copy(x)
x[2]=10
print(x)
print(z)

# note: copy makes an array
# to make a list from an array use 
# from numpy import ndarray
#  ndarray.tolist(np.array(alist))
[ 1.  2. 10.  4.]
[1. 2. 3. 4.]

variables are passed by number

In [34]:
z=1  # variables  are passed by numbers
y=z
z=2
## Question: what will happen?
print(y)   
## Answer: y is not changed
1
In [37]:
def addone(x):  # passes by number if x is a variable!
    x+= 1   # nothing is returned

## Question: if a variable x is passed will it change?
## Question: if an array x is passed will it change?
In [39]:
x = 1 
addone(x)
print(x)  
# Answer: variable x is not changed
1

arrays are passed by pointer

In [40]:
x = np.array([1,2])
addone(x)
# Question: will the array x change?
print(x)  # Answer: array x is changed!
[2 3]

local vs global variables

In [41]:
def f(x):
    y = x+7 + b_var  # b_var is not defined locally, assumed to be a global variable
    return y
# Question:  what will happen?
f(1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-41-c40725b5ec8f> in <module>
      2     y = x+7 + b_var  # b_var is not defined locally, assumed to be a global variable
      3     return y
----> 4 f(1)

<ipython-input-41-c40725b5ec8f> in f(x)
      1 def f(x):
----> 2     y = x+7 + b_var  # b_var is not defined locally, assumed to be a global variable
      3     return y
      4 f(1)

NameError: name 'b_var' is not defined
In [ ]:
## Answer: b_var was not defined locally and we had not
# defined a variable called b_var globally
# the variable is not defined.
In [45]:
b_var=1  # defined globally 
## Question: Now what will happen?
print(f(1))
9
In [ ]:
# Answer: we defined a global variable b_var which is used within the routine f()
In [46]:
b_var=1
def f(x):
    b_var=2  # defined locally 
    y = x+7 + b_var  
    return y
print(f(1))
## Question: is b_var changed? 
print(b_var) # Answer, no b_var is not changed! (before it was 1)
10
1
In [ ]:
# Answer: Locally defined variables overide those that are defined globally

what does this function do?

In [47]:
def f(x):
    x = 2
    return x**2
## Question: what does this function do?
In [48]:
print(f(2))
print(f(3))
4
4
In [ ]:
# Answer:  locally defined variables overide the ones that 
# are passed as arguments to a function.

making arrays!

numpy routines: linspace, arange, and zeros

In [4]:
t = np.arange(0,1,0.1)   # arguments: start, stop-increment, increment
t
Out[4]:
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
In [49]:
t = np.linspace(0,1,101)   # allocating a nice long vector
# arguments: start, stop, number of elements
t
Out[49]:
array([0.  , 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 ,
       0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2 , 0.21,
       0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3 , 0.31, 0.32,
       0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4 , 0.41, 0.42, 0.43,
       0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5 , 0.51, 0.52, 0.53, 0.54,
       0.55, 0.56, 0.57, 0.58, 0.59, 0.6 , 0.61, 0.62, 0.63, 0.64, 0.65,
       0.66, 0.67, 0.68, 0.69, 0.7 , 0.71, 0.72, 0.73, 0.74, 0.75, 0.76,
       0.77, 0.78, 0.79, 0.8 , 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87,
       0.88, 0.89, 0.9 , 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98,
       0.99, 1.  ])

array arithmetic

In [50]:
t = np.linspace(0,1,11)
y=np.sin(6.0*t)   # on the whole array at once! 

It is faster to do arithmetic and functions of whole arrays than to loop over the array via each index.

Many numpy routines will work on arrays. Many math routines will not.

In [ ]:
# this is slower but does the same thing
y = np.zeros(len(t)) # allocate 
for i in range(len(t)):  # loop for each index of the array
    y[i] = np.sin(6*t[i])  # compute for each element of the array 

making a plot!

In [51]:
# let the notebook know you want plots in the notebook
%matplotlib inline
# load in the plotting package!
import matplotlib.pyplot as plt


plt.xlabel("time", fontsize=22) # a nice plot with labels
plt.ylabel("sine!", fontsize=22)
plt.plot(t,y, 'ro')  # red points
plt.plot(t,y, 'k-')  # black line
Out[51]:
[<matplotlib.lines.Line2D at 0x7f8054d952e0>]
In [53]:
z = np.zeros(10)  # another handy way to allocate an array
z
Out[53]:
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

numpy.append

It is often very useful to be able to add to an array.

This requires allocating more space for it.

In [56]:
z=np.arange(0,3,0.2)
bunch_of_zeros=np.zeros(10)

combined_array = np.append(z,bunch_of_zeros)
print(combined_array)
[0.  0.2 0.4 0.6 0.8 1.  1.2 1.4 1.6 1.8 2.  2.2 2.4 2.6 2.8 0.  0.  0.
 0.  0.  0.  0.  0.  0.  0. ]

an if statement

In [57]:
def using_if(x):  # example of an if statement
    if (x == 3):
        print("x is equal to 3")
    else:
        print("x is not equal to 3")
In [58]:
using_if(2)
x is not equal to 3
In [59]:
using_if(3)
x is equal to 3
In [ ]: