# Basic Python¶

## Lesson 1: Expressions, variables and built-in functions¶

### Expressions¶

An expression describes a computation. Python evaluates expressions and generates a value. We say that expressions "evaluate to" their result.

2019

2019


Python's arithmetic operators allows you to use a Python command line or Jupyter notebook cell as a "calculator"

2000 + 19

2019

2000 - 19

1981


Multiplication is done with an asterisk *

1 * 2 * (3 * 4)

24


Normal or "true" division is done with /. This operation will always return a float

10 / 2

5.0


Python has two other division operators. "Floor" division //, which returns the division rounded down to the lowest integer, and the modulo operator %, which returns the remainder of a division after substracting the next lowest integer. These are easier to understand by example:

10 // 6

1

10 % 6

4

6 // 2

3

6 % 3

0


To take an exponent, use two asterisks ** (NOT ^)

2 ** 3

8


### Variables¶

* Variables are names for values. * In Python the = symbol assigns the value on the right to the name on the left. * The variable is created when a value is assigned to it. * Every variable has a type that describes what sort of data it contains. Some of the most common types are int (integer), float (floating point number), and string (text) * Unlike many other languages, in Python you do not have to specify the type when you create a variable. Python infers the data type based on the context. This is called 'duck typing'.

int variables are simply numbers. Let's assign 27 to a variable 'age'. If the variable age does not already exist, this assignment expression will create it

age = 27


You can find the type of a variable using the type() function. Let's examine the type of age.

type(age)

int


float variables are created by adding a decimal point to a number. Let's redefine age as 27.0 and check the type

age = 27.0

type(age)

float


string variables contain text and are created using quotation marks. Both single and double quotation marks are OK. Let's try making age a string

first_name = "Ryan"

type(first_name)

str


Note that it's possible to create a string that contains only numbers

age = "27"

type(age)

str


In the Jupyter notebook, variable names are preserved between cells. In more formal language, the namespace of a notebook is preserved unless the kernel is reset, which resets all of the variable names. You can see this if you execute the following cells out of sequence. Try it out. Also try resetting the kernel and executing just the latter half.

age = 42

age

42


Assigning a new value to an existing variable will replace the value of that variable

age = 29

age

29


### Built-in functions¶

Now that we understand how Python and Jupyter handle variables, let's talk about built-in functions. These functions are available by default without issuing any special instructions. One such function is type, which we've already used.

Functions are called using the function name and parentheses, which enclose the function arguments. In the example below, print is the function, and the string "Hello world!" is the argument.

print("Hello world!")

Hello world!



print can accept multiple arguments, separate by commas, and will combine them together to generate its output, like this:

print("Age is", age, "years")

Age is 29 years



One of the most important things you can know when learning programming is where to access help on the things you're trying to use. There are a number of ways to access information on a function. Three of the easiest ways in Jupyter are

1. Place your cursor inside the name of any function, and press SHIFT+TAB. This will open a small box with function information, which can be expanded by pressing tab again.
2. Use the built-in help function, where the argument to help is the name of the function you want to know more about.
3. Type the name of the function followed by ?, which will show the functions documentation or 'docstring'

#### Finding help¶

## click your cursor inside 'print' and press SHIFT+TAB
print("this is cool")

this is cool


help(print)

Help on built-in function print in module builtins:

print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:  a file-like object (stream); defaults to the current sys.stdout.
sep:   string inserted between values, default a space.
end:   string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.



print?


#### Importing other modules and functions¶

To get a function that's not built in to Python, we use the import statement. In this example, we're going to import a module called math that contains a number of functions that can be accessed by using math.FUNCTION_NAME_HERE.

import math

math.exp(2)

7.38905609893065

print("Exponent of 2:", math.exp(2))
print("Sine of 3.1415:", math.sin(3.1415))

Exponent of 2: 7.38905609893065
Sine of 3.1415: 9.265358966049024e-05



The Standard library includes a number of modules that come pre-installed with the python programming language itself, which is summarized in this documentation. Python's real power, however, comes in how extensible it is. Python has an ecosystem of external libraries that provide special functions for many different tasks. Three of the most common external libraries in python are:

• numpy - for efficient numerical array manipulation and operation
• scipy - for a number of tools related to scientific computing
• matplotlib - for plotting data and creating figures

Let's use some functions from numpy and matplotlib to create a plot

import numpy as np
from matplotlib import pyplot
%matplotlib inline

average = np.average(inflammation, axis=0)
pyplot.plot(average)

[<matplotlib.lines.Line2D at 0x7f97f8648580>] ## Lesson 2: Lists and Strings¶

### A list stores many values in a single structure.¶

• A list stores many values together.
• Contained within square brackets [...].
• Values separated by commas ,.
• Use len to find out how many values are in a list.
pressures  = [0.273, 0.275, 0.277, 0.275, 0.276]
print('pressures:', pressures)

pressures: [0.273, 0.275, 0.277, 0.275, 0.276]



### Use the built-in function len to find the length of a list¶

len(pressures)

5


### Lists may be heterogeneous¶

• Values can have different types
goals = [1, 'Create lists.', 2, 'Extract items from lists.',
3, 'Modify lists.']


### Index and slice to get information out of a string/list¶

• Locations are numbered from 0 rather than 1
• Negative indices count backward from the end of the string
• Slices include the lower bound but exclude the upper bound, so (upper - lower) is the slice's length
numbers = ["one", "two", "three", "four", "five"]

print('first element:', numbers)
print('last element:', numbers[-1])
print('middle elemnets:', numbers[2:5])

first element: one
last element: five
middle elemnets: ['three', 'four', 'five']



Indexing beyond the end of a collection is an error

# NBVAL_RAISES_EXCEPTION
## This code will fail
print('99th element of numbers is:', numbers)

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-38-89d4ca35c24b> in <module>
1 # NBVAL_RAISES_EXCEPTION
2 ## This code will fail
----> 3 print('99th element of numbers is:', numbers)

IndexError: list index out of range

### List values can be replaced by assigning to them¶

• Use an index expression on the left of assignment to replace a value.
• We say that lists are mutable because their contents can be changed after they are created
pressures = 0.265
print('pressures is now:', pressures)

pressures is now: [0.265, 0.275, 0.277, 0.275, 0.276]



### Appending items to a list lengthens it¶

• use list_name.append to add items to the end of a list.
primes = [2, 3, 5]
print('primes is initially:', primes)
primes.append(7)
primes.append(9)
print('primes has become:', primes)

primes is initially: [2, 3, 5]
primes has become: [2, 3, 5, 7, 9]



* append is a method of lists * like a function, but tied to a particular object

• Use object_name.method_name to call methods
• deliberately resembles the way we refer to things in a library

• We will meet other methods of lists as we go along

• Use help(list) for a preview

### Extending a list adds another list to it¶

extend is similar to append, but it allows you to combine two lists.

teen_primes = [11, 13, 17, 19]
older_primes = [23, 31, 47, 59]
print('primes is currently:', primes)
primes.extend(teen_primes)
print('primes has now become:', primes)
primes.append(older_primes)
print('primes has finally become:', primes)

primes is currently: [2, 3, 5, 7, 9]
primes has now become: [2, 3, 5, 7, 9, 11, 13, 17, 19]
primes has finally become: [2, 3, 5, 7, 9, 11, 13, 17, 19, [23, 31, 47, 59]]



Note that while extend maintains the "flat" structure of the list, appending a list to a list makes the result two-dimensional.

### Use del to remove items from a list entirely¶

• del list_name[index] removes an item from a list and shortens the list.
• Not a function or method, but a statement in the language.
print('primes before removing item:', primes)
del primes
print('primes after removing item:', primes)

primes before removing last item: [2, 3, 5, 7, 9, 11, 13, 17, 19, [23, 31, 47, 59]]
primes after removing last item: [2, 3, 5, 7, 11, 13, 17, 19, [23, 31, 47, 59]]



### The empty list contains no values¶

• [] is "the zero of lists"
• Helpful as a starting point for collecting values
• NEVER use an empty list as a default argument in a function!

### Strings can be sliced and indexed just like lists¶

• You can think of strings as lists of characters
greeting = "My name is Ryan"
print('first character:', greeting)
print('last character:', greeting[-1])
print('middle character:', greeting[2:5])

first character: M
last character: n
middle character:  na



### Unlike lists, strings are immutable¶

• Cannot change the characters in a string after it has been created.
• Python considers the string to be a single value with parts, not a collection of values.
# NBVAL_RAISES_EXCEPTION
element = 'helium'
## This code will fail
element = 'C'

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-44-789481aab7e2> in <module>
2 element = 'helium'
3 ## This code will fail
----> 4 element = 'C'

TypeError: 'str' object does not support item assignment

## Lesson 3: For loops¶

A for loop can be used to repeat actions over a set of values. Let's print each letter in this list:

name = ['J', 'i', 'm', 'm', 'y']

for letter in name:
print(letter)

J
i
m
m
y



### For loop syntax¶

For loops are constructed via the syntax for LOOP_VARIABLE in ITERABLE. The loop variable in the above example I've used is letter and the iterable I've used is the list name, which was defined as '['J', 'i', 'm', 'm', 'y']'. Other iterables include strings and dictionary keys, among others. For example, we could make name a string and iterate through it in the same way we iterated through the list:

name = 'Jimmy'

for letter in name:
print(letter)

J
i
m
m
y



You can also use list indexing notation to limit iteration to a certain portion of an iterable.

name = 'Jimmy'

for letter in name[0:3]:
print(letter)

J
i
m



Iterables have a length, and you can find this length using the len function.

print("Length of", name, "is", len(name))

Length of Jimmy is 5



### Use enumerate() to get both an index and an item¶

The enumerate function assigns an index (or counter) to each value of an iterable. It returns a tuple of (counter, value) that can be useful in for loops. For example, here we assign the index to the variable n and the value of the iterable to letter:

for n, letter in enumerate(name):
print("Letter", n, "-", letter)

Letter 0 - J
Letter 1 - i
Letter 2 - m
Letter 3 - m
Letter 4 - y



### Use zip() to loop over two iterables simultaneously¶

The zip function can be used to loop through two iterables simultaneously (like two sides of a zipper). Here, we use zip to iterate through two strings that have the same length

for letter1, letter2 in zip("Jimmy", "Heath"):
print(letter1, letter2)

J H
i e
m a
m t
y h



### Use range() to iterate ranges of numbers¶

The range function is used to construct an iterable corresponding to a set of numbers beginning at 0 and ending at a certain number:

for number in range(6):
print(number)

0
1
2
3
4
5



### Logic within for loops¶

range can take multiple arguments, where the first argument is interpreted as the beginning of the range.

In the example below, we combine a for loop with an if statement to print only the even numbers. This makes use of the modulo % operator we covered in the Variables lesson.

for number in range(2, 10):
if number % 2 == 0:
print(number, "is even")

2 is even
4 is even
6 is even
8 is even



### break stops the loop¶

The break statement is used to stop iterating through an iterable if some condition is met. Here, we will end our loop as soon as we encouter the number 6:

for number in range(2, 10):
if number == 6:
break
else:
print(number)

2
3
4
5



A common use of for loops is to keep track of a running total of numbers. In this pattern, it's important to declare the variable that you're adding to outside the scope of the for loop.

The example below makes use of the "in place addition" += operator, which says "add the value on the right of the operator to the value of the variable on the left". So x += 5 means "add 5 to the current value of variable x. Python has similar "in place" operators for several other operations, including -=, *=, and /= for subtraction, multiplication, and division, respectively.

my_sum = 0

for number in range(6):
my_sum += number
print("Sum of numbers from 0 to 5 is", my_sum)

Sum of numbers from 0 to 5 is 15