Welcome to Jupyter Notebooks and Python!¶

Jupyter notebooks (formerly IPython Notebooks) are frameworks to write reports, prototype code, and make presentations. Jupyter can run different kernels (i.e. programming languages) like C++, Julia, R, etc. For the rest of this tutorial, we focus on using Python 3.6.*

Outline¶

  • Best practices
  • Overview
    • LaTeX
  • Importing Packages/Built-In Functions
  • Python Data Structures
    • Variables
    • Lists & Strings
  • Conditional Statements

As in all things, it takes practice, patience, and passion.¶

In [1]:
#from IPython.display import Video
from IPython.display import HTML

HTML("""
<video width="640" height="480" controls>
  <source src="howtocode.mp4" type="video/mp4">
</video>
""")
Out[1]:

Best practices ¶

1) For coding environments, provide detailed comments for interpretability and reproducibility. This will also help the future you when you come back to past assignments/code.

2) Read the error message when your code does not work. They contain important information on how to debug your code.

3) If you do something more than twice, automate that action.

4) Write code that works first, then optimize!

5) Notebooks can be split if they get too long. You want to be able to come back to a notebook without too much trouble and searching.

Python Overview ¶

Python is a dynamic, interpreted language. Variables do not need to be declared and the code does not need to be compiled. In short, the Python interpreter will attempt to make sense of your code and will raise an error if something goes wrong.

In Python, comments in code start with a #. In Jupyter notebooks, you also have the option of making it cell a Markdown cell.

Practice! Below, try making

  • a comment cell
  • a Markdown cell

I can start typing

In [2]:
# this is my first comment. I'm going to add some numbers
3 + 4
Out[2]:
7

$\LaTeX$ input ¶

Markdown cells also support $\LaTeX$ input with either $ or \begin{equation}

Practice! Create a Markdown cell with $\LaTeX$!

For example, $f(x) = x^2$.

In [3]:
type(2)
Out[3]:
int
In [4]:
type(42.0)
Out[4]:
float
In [5]:
type('hello world')
Out[5]:
str

These values belong to different types: 2 is an integer, 42.0 is a floating-point number, and 'Hello, World!' is a string, so-called because the letters it contains are strung together.

Some random/built-in functions are

  • abs()
  • help()
  • print()
In [6]:
help(abs)
Help on built-in function abs in module builtins:

abs(x, /)
    Return the absolute value of the argument.

Practice! What happens if you try $\texttt{ print(abs(-100)) + 100}$?

In [7]:
type(print(abs(-100)))
100
Out[7]:
NoneType
In [8]:
type(100 + 2.0)
Out[8]:
float

Importing Packages & Built-In Functions ¶

In [9]:
# import ... imports packages and follows the structure 
# import [package name]
import sys
sys.version
Out[9]:
'3.8.5 (default, Sep  3 2020, 21:29:08) [MSC v.1916 64 bit (AMD64)]'
In [10]:
# Jupyter notebooks also support tab completion
sys.v
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-10-bdeb1f1b5d8e> in <module>
      1 # Jupyter notebooks also support tab completion
----> 2 sys.v

AttributeError: module 'sys' has no attribute 'v'

Python Data Structures ¶

Variables ¶

Variables, just as in mathematics, are placeholders for values assigned to them. Functions, on the other hand, take input (like variables) and output the result of applying certain rules to the input.

In [11]:
# Define two variables and add them
In [12]:
# Using variables as input to a function
help(sum)
Help on built-in function sum in module builtins:

sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
    
    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.

In [13]:
# Multiply two variables, and save as another variable
a = 2
b = 3 
a * b
Out[13]:
6
In [14]:
c
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-14-2b66fd261ee5> in <module>
----> 1 c

NameError: name 'c' is not defined
In [15]:
# Raise one variable to the power of another variable
# pow(2,3)
2 ** 3
Out[15]:
8
In [16]:
# Compare two variables
a > b
a < b 
a == b
Out[16]:
False
In [17]:
# division
print(4 / 3) # / performs division
# remainders # % outputs remainder when dividing by second number
print(4 % 3)
1.3333333333333333
1

Practice! Create three variables and practice adding, multiplying, dividing, etc.

In [18]:
type(2)
Out[18]:
int
In [19]:
type(.1)
Out[19]:
float
In [20]:
.1 + .3000000000000001
Out[20]:
0.40000000000000013

Lists and strings ¶

We now shift our focus to other data structures, lists and strings. Strings, lists, and tuples are all sequence types are ordered collection of objects. Lists are enclosed in square brackets ([ and ]) and tuples in parentheses (( and )).

Lists are mutable (can be changed) and tuples are immutable (cannot be changed) .

** NOTE: Python is 0-indexed, so keep this in mind when writing loops, accessing elements, etc.

In [21]:
a = 'mystring'
In [22]:
print(a)
mystring
In [23]:
list_num = [1,2,3,4,5] # this is a list
tup_num = (1,2,3,4,5) # this is a tuple
In [24]:
list_num * 4
Out[24]:
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
In [25]:
# let's make a list of fruits
fruits = ['apples', 'figs', 'oranges']
fruits[1]
Out[25]:
'figs'
In [26]:
fruits.append('mango')
print(fruits)
['apples', 'figs', 'oranges', 'mango']
In [27]:
fruits.insert(1,'cherry')
In [28]:
fruits
Out[28]:
['apples', 'cherry', 'figs', 'oranges', 'mango']
In [29]:
# Functions have the following structure

# def myfun(input):
#       input operations
#       return output
In [30]:
def sumfun(a,b):
    return a+b
In [31]:
def sumfun2(a,b):
    out = a + b
    return out
In [32]:
sumfun(3,-1)
sumfun2(3,-1)
Out[32]:
2
In [33]:
def myname():
    print('Hello Mario!')
In [34]:
myname()
Hello Mario!

Try the following exercises on your own:

1) Write a function that takes two inputs (a and b) and outputs a^b + b.

2) Write a function that takes no inputs and prints "Your code has finished!"

In [35]:
def mypow(a,b):
    first_term = pow(a,b)
    mysum = first_term + b
    return mysum

Conditional statements ¶

In python, you check conditions with an if statement

In [36]:
x = 5
if x > 10: # the first condition checks if x is greater than 10
    print(x)
elif x < 3:
    print(x+4)
else: 
    print('x does not satisfy the conditions.')
x does not satisfy the conditions.

Recall that the Fibonacci numbers are of the form $$F_n = F_{n-1} + F_{n-2},$$ where $F_0 = 0, F_1 = 1$.

The first few numbers in the sequence are $$ 0,1,1,2,3,5,8,13,21,34,55 $$

In [ ]:
 
In [37]:
x = 8

def myfun(x):
    if x > 10: # the first condition checks if x is greater than 10
        print(x)
    elif x < 3:
        print(x+4)
    else: 
        x = x + myfun(x) 
        print(x)
        #print('x does not satisfy the conditions.')
In [38]:
myfun(x)
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-38-366cd113e535> in <module>
----> 1 myfun(x)

<ipython-input-37-a8190f3474c1> in myfun(x)
      7         print(x+4)
      8     else:
----> 9         x = x + myfun(x)
     10         print(x)
     11         #print('x does not satisfy the conditions.')

... last 1 frames repeated, from the frame below ...

<ipython-input-37-a8190f3474c1> in myfun(x)
      7         print(x+4)
      8     else:
----> 9         x = x + myfun(x)
     10         print(x)
     11         #print('x does not satisfy the conditions.')

RecursionError: maximum recursion depth exceeded in comparison