Chapter 2 - Introduction to Python

We will be using the Jupyter notebook for many activities this semester. Every notebook has an associated language called the "kernel". We will be using in the Python 3 kernel from the IPython project.

For more information on how to use the notebook, please read the following (which is also a notebook written by a Bryn Mawr student):

1. Python

Python is a programming language that has been under development for over 25 years [1].

This Chapter will not cover everything in Python. If you would like, please consider the following resources:

Getting Started with Python:

Learning Python in Notebooks:

This is handy to always have available for reference:

Python Reference:

1.1 Statements

Python is an imperative language based on statements. That is, programs in Python consists of lines composed of statements. A statement can be:

  • a single expression
  • an assignment
  • a function call
  • a function definition
  • a statement; statement

1.1.1 Expressions

  • Numbers
    • integers
    • floating-point
    • complex numbers
  • strings
  • boolean values
  • lists and dicts

1.1.1.1 Numbers

In [ ]:
1
In [ ]:
2
In [ ]:
-3
In [ ]:
1
2
In [ ]:
3.14

1.1.1.2 Strings

In [ ]:
'apple'
In [ ]:
"apple"

Notice that the Out might not match exactly the In. In the above example, we used double-quotes but the representation of the string used single-quotes. Python will default to showing representations of values using single-quotes, if it can.

1.1.1.3 Boolean Values

In [ ]:
True
In [ ]:
False

1.1.1.4 Lists and Dicts

Python has three very useful data structures built into the language:

  • dictionaries (hash tables): {}
  • lists: []
  • tuples: (item, ...)

List is a mutable list of items. Tuple is a read-only data structure (immutable).

In [ ]:
[1, 2, 3]
In [ ]:
(1, 2, 3)
In [ ]:
1, 2, 3
In [ ]:
{"apple": "a fruit", "banana": "an herb", "monkey": "a mammal"}
In [ ]:
{"apple": "a fruit", "banana": "an herb", "monkey": "a mammal"}["apple"]

1.1.2 Function Calls

There are two ways to call functions in Python:

  1. by pre-defined infix operator name
  2. by function name, followed by parentheses

Infix operator name:

In [ ]:
1 + 2
In [ ]:
abs(-1)
In [ ]:
import operator
In [ ]:
operator.add(1, 2)

1.1.2.1 Print

Evaluating and display result as an Out, versus evaluating and printing result (side-effect).

In [ ]:
print(1)

1.1.3 Special Values

In [ ]:
None

1.1.4 Defining Functions

In [ ]:
def plus(a, b):
    return a + b
In [ ]:
plus(3, 4)
In [ ]:
def plus(a, b):
    a + b
In [ ]:
plus(3, 4)

What happened? All functions return something, even if you don't specify it. If you don't specify a return value, then it will default to returning None.

In [ ]:
"a" + 1

Sidebar 2-1: How to Read Python Error Messages

Python error messages

TypeError: Can't convert 'int' object to str implicitly

Above the error message is the "traceback" also called the "call stack". This is a representation of the sequence of procedure calls that lead to the error. If the procedure call originated from code from a file, the filename would be listed after the word "File" on each line. If the procedure call originated from a notebook cell, then the word "ipython-input-#-HEX".

1.2 Equality

1.2.1 ==

In [ ]:
1 == 1

1.2.2 is

In [ ]:
[] is []
In [ ]:
list() is list()
In [ ]:
tuple() is tuple()
In [ ]:
57663463467 is 57663463467

2. Advanced Topics

The Zen of Python:

In [ ]:
import this

Python evolves. But there are limits:

In [ ]:
from __future__ import braces

2.1 Python Warts

2.2 Scope of variables

Is not always clear:

In [ ]:
y = 0
for x in range(10):
    y = x
In [ ]:
x
In [ ]:
[x for x in range(10, 20)]
In [ ]:
x

2.3 Scope

Python follows the LEGB Rule (after https://www.amazon.com/dp/0596513984/):

  • L, Local: Names assigned in any way within a function (def or lambda)), and not declared global in that function.
  • E, Enclosing function locals: Name in the local scope of any and all enclosing functions (def or lambda), from inner to outer.
  • G, Global (module): Names assigned at the top-level of a module file, or declared global in a def within the file.
  • B, Built-in (Python): Names preassigned in the built-in names module : open, range, SyntaxError,...
In [ ]:
x = 3
def foo():
    x=4
    def bar():
        print(x)  # Accesses x from foo's scope
    bar()  # Prints 4
    x=5
    bar()  # Prints 5
In [ ]:
foo()

See scope_resolution_legb_rule.ipynb for some additional readings on scope.

2.4 Generators

In [ ]:
def function():
    for i in range(10):
        yield i
In [ ]:
function()
In [ ]:
for y in function():
    print(y)

2.5 Default arguments

In [ ]:
def do_something(a, b, c):
    return (a, b, c)
In [ ]:
do_something(1, 2, 3)
In [ ]:
def do_something_else(a=1, b=2, c=3):
    return (a, b, c)
In [ ]:
do_something_else()
In [ ]:
def some_function(start=[]):
    start.append(1)
    return start
In [ ]:
result = some_function()
In [ ]:
result
In [ ]:
result.append(2)
In [ ]:
other_result = some_function()
In [ ]:
other_result

3.2 List comprehension

"List comprehension" is the idea of writing some code inside of a list that will generate a list.

Consider the following:

In [ ]:
[x ** 2 for x in range(10)]
In [ ]:
temp_list = []
for x in range(10):
    temp_list.append(x ** 2)
temp_list

But list comprehension is much more concise.

3.3 Plotting

In [ ]:
%matplotlib notebook

After the magic, we then need to import the matplotlib library:

In [ ]:
import matplotlib.pyplot as plt

Python has many, many libraries. We will use a few over the course of the semester.

To create a simple line plot, just give a list of y-values to the function plt.plot().

In [ ]:
plt.plot([5, 8, 2, 6, 1, 8, 2, 3, 4, 5, 6])

But you should never create a plot that doesn't have labels on the x and y axises, and should always have a title. Read the documentation on matplotlib and add labels and a title to the plot above:

http://matplotlib.org/api/pyplot_api.html

Another commonly used library (especially with matplotlib is numpy). Often imported as:

2.6 Closures

Are functions that capture some of the local bindings to variables.

In [ ]:
def return_a_closure():
    dict = {}
    def hidden(operator, value, other=None):
        if operator == "add":
            dict[value] = other
        else:
            return dict[value]
    return hidden
In [ ]:
thing = return_a_closure()
In [ ]:
thing("add", "apple", 42)
In [ ]:
thing("get", "apple")
In [ ]:
thing.dict

Where is dict?

See http://www.programiz.com/python-programming/closure for more examples.