Introduction to Python

With Mark Lavin

Course Info

The book for this section of the course is Mark Pilgram’s “Dive into Python 3”. The full book is available online at http://www.diveintopython3.net/

My lecture notes (including source) and code examples are available at https://github.com/mlavin/lecture-notes

What is Python?

XKCD 353

There is More than One Python

Standard Python

  • Python 2.X - Last stable release 2.7.14
  • Python 3.X - Currently 3.6.4

Non-standard Python

  • Jython - Python implementation written in Java
  • IronPython - Python implementation written in .NET
  • Cython - Python extension for writing C/C++ extensions
  • PyPy - Python implementation written in Python (sort of)

Which Python Should I Use?

Python 3.5+

I'm running 3.6 for these examples but 3.5 is great too

Where can I get Python?

You use Linux or a Mac then you probably already have Python 2.7 but you'll probably want a more recent version

For Mac I suggest pyenv or Homebrew

If you use Windows you can download an executable installer from Python.org

Who Uses Python?

4th on the TIOBE Index as of Feb 2018 below Java, C, and C++

Companies like:

  • Web: Google, Reddit, Pintrest, Instagram, and Caktus Group
  • Fortune 500: Honeywell, Phillips, and Red Hat
  • Researchers and universities: NCSU, UNC, and Duke
  • Other: Industrial Light & Magic and Disney

Read more: http://www.python.org/about/success/

In [3]:
# %load ../code/hello.py
# hello.py

print('Hello, World')
Hello, World
In [5]:
# %load ../code/fibonacci.py
def fibonacci(n):
    if n <= 2:
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

for i in range(1, 15):
    print(fibonacci(i))
1
1
2
3
5
8
13
21
34
55
89
144
233
377

Learn to Love Whitespace

Python was created with the idea that most code will be read more times than it’s written.

Whitespace is meaningful for seperating code blocks without the use of braces.

The pass statement can be used to hold an empty logical or function block.

PEP8

The convention is to use 4 spaces per indention and you cannot mix tabs and spaces.

Suggested max line length is 79 characters. Backslash is a line continuation character but lines can also be extended with parentheses.

def my_long_function(arg1, arg2, optional_arg1="fizz",
                     optional_arg2="buzz", optional_arg3="done"):
    pass

You can read the full style guide online http://www.python.org/dev/peps/pep-0008/

In [5]:
import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

Declaring Functions

Functions are declared with the def keyword:

def my_function():
    pass

Arguments can given starting with required then optional:

def short_name(first_name, last_name="Smith"):
    return "%s %s" % (first_name[0], last_name)

Notice that the arguments do not declare their type.

Typing

Python is dynamically typed meaning you do not need to declare the types of your variables before using them. The variable type is determined when the program is executed.

Python is strongly typed meaning that type is enforced.

In [10]:
a = 1 # a is now an integer
b = '2' # b is now a string
a + b # this will fail
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-77cf1aad6cf7> in <module>()
      1 a = 1 # a is now an integer
      2 b = '2' # b is now a string
----> 3 a + b # this will fail

TypeError: unsupported operand type(s) for +: 'int' and 'str'
In [11]:
str(a) + b
Out[11]:
'12'

Type Annotations

New in Python 3.5 - (PEP484)[https://www.python.org/dev/peps/pep-0484/]

You can annotate your functions with the types they take/return

def short_name(first_name: str, last_name="Smith": str) -> str:
    return "%s %s" % (first_name[0], last_name)

This can help document your code but this isn't enforced at runtime.

Everything is an Object

Everything has:

  • An identity
  • A type
  • Some content

Great expanation of Python Object model: http://www.effbot.org/zone/python-objects.htm

In [12]:
import math

math.sqrt(4)
Out[12]:
2.0
In [14]:
math.sqrt.__doc__
Out[14]:
'sqrt(x)\n\nReturn the square root of x.'
In [16]:
# %load ../code/fibo2.py
import time


def fibonacci(n):
    if n <= 2:
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

start = time.time()
fibonacci(25)
time.time() - start
Out[16]:
0.11204242706298828
In [20]:
# %load ../code/fibocache.py
import time


def fibonacci(n):
    if hasattr(fibonacci, '_%s' % n):
        return getattr(fibonacci, '_%s' % n)
    if n <= 2:
        value = 1
        setattr(fibonacci, '_%s' % n, value)
        return value
    else:
        value = fibonacci(n - 1) + fibonacci(n - 2)
        setattr(fibonacci, '_%s' % n, value)
        return value

start = time.time()
fibonacci(25)
time.time() - start
Out[20]:
0.00019669532775878906
In [21]:
fibonacci._10
Out[21]:
55
In [23]:
fibonacci._11
Out[23]:
89
In [3]:
import math

def do_math(f, x):
    print(f(x))

y = math.sqrt
do_math(y, 10)
y = math.log
do_math(y, 10)
3.1622776601683795
2.302585092994046
In [24]:
import math

math.log(10)
Out[24]:
2.302585092994046
In [25]:
def new_log(x):
    return 5

math.log = new_log
math.log(10)
Out[25]:
5

What Do I Put in The Function?

Many of the same operators you know and love from C:

# add, subtract, multiply, divide
a + b, a - b, a * b , a / b
# exponentiation, floor divide, modulo
a ** b, a // b, a % b
# bitwise inverse, left bit shift, right bit shift
~a, a << b, a >> b
# bitwise and, bitwise or, bitwise xor
a & b, a | b, a ^ b

Comparisons And Logic

Most will be familiar:

# less than, less equal, greater than, greater equal
a < b, a <= b, a > b, a >= b
# equal, not equal, object identity, object identity negation
a == b, a != b, a is b, a is not b
# collection membership, collection membership negation
a in b, a not in b
# logical and, logical or, logical negation
a and b, a or b, not a

Comparisons Can be Chained

x < 10 and x > 5

is the same as

5 < x < 10

Control Statements

The basic flow control statements should also look familiar from C though the syntax is slightly different.

if, else, for, while

The same as with functions there are no braces to define the logical blocks. Instead everything is defined by the whitespace indention.

If

The if statement defines a control block which will only execute when a logical statement is true. This can be paired with an else statement to define how to handle the false case. To avoid deep nesting you can also use elif statement.

if x > 100:
    print("That's a lot!")
elif x > 10:
    print("That's ok.")
else:
    print("That's all you've got?")

For

The for statement is used to loop through any iterable. This includes lists and strings. User defined type can also have the ability to be iterated by defining the iteration protocol.

for x in [1, 2, 3]:
    print(x)

You can use the enumerate function to add the current index.

for i, c in enumerate("blip"):
    print("Character %s is %s" (i, c))

Range

range allows you to generate a sequence of integers between a particular range. It starts at zero and increases by one but those are available arguments.

In [5]:
for i in range(5):
    print(i)
0
1
2
3
4
In [6]:
for i in range(1, 5):
    print(i)
1
2
3
4
In [7]:
for i in range(1, 5, 2):
    print(i)
1
3
In [9]:
for name in ['Newton', 'x', 'Euler']:
    if 'x' in name:
        continue
    else:
        print(name)

for name in []:
    print("Names were given.")
else:
    print("No names were given.")
Newton
Euler
No names were given.

While

In addition to the for loop there is also the while loop. The while loop will continue until a particular logical statement is false.

x = 10
while x > 5:
    x -= 1

Pass

pass is a special keyword in Python that does nothing. It can be used to fill a control block or a function or a class definition.

Comments

Python comments are denoted with the # character. While not techinally a comment you can also use triple quoted strings as a multi-line comment. This is the style used to define doc strings previously discussed.

# My Comment

"""
This is a longer comment.
Blah blah blah.
Though technically it's a string literal.
"""

Building Python Module

Python modules are collections of Python statements. They stored in text files with the .py extension. The module name is the same as the file name without the extension.

Modules as Scripts

When you pass a module to the interpreter such as python hello.py the module name changes from hello to __main__. You can use this fact to handle the case where the module is executed differently than when the module is imported.

if __name__ == "__main__":
    print("I am a script.")
else:
    print("I am a module.")

Imports

We’ve already seen some import statements but there are three styles of Python imports.

# Add a reference to the module
import X
# Creates references to all public objects in X
from X import *
# Creates refernces to the names a, b, c
from X import a, b, c
# Add a reference to the module
X = __import__('X')

Python Path

Where does Python look for modules to import? The Python path.

This is defined by the PYTHONPATH environment variable in your shell.

In [10]:
import sys

sys.path
['', '/home/mark/.virtualenvs/lectures/lib/python36.zip', '/home/mark/.virtualenvs/lectures/lib/python3.6', '/home/mark/.virtualenvs/lectures/lib/python3.6/lib-dynload', '/usr/lib/python3.6', '/home/mark/.virtualenvs/lectures/lib/python3.6/site-packages', '/home/mark/.virtualenvs/lectures/lib/python3.6/site-packages/IPython/extensions', '/home/mark/.ipython']

What Happens on Import?

When Python imports a module, it first checks the module registry (sys.modules) to see if the module is already imported. If that’s the case, Python uses the existing module object as is.

Otherwise, Python does something like this:

  • Create a new, empty module object (this is essentially a dictionary)
  • Insert that module object in the sys.modules dictionary
  • Load the module code object (if necessary, compile the module first)
  • Execute the module code object in the new module’s namespace. All variables assigned by the code will be available via the module object.
In [12]:
import math

dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']
In [13]:
help(math)
Help on built-in module math:

NAME
    math

DESCRIPTION
    This module is always available.  It provides access to the
    mathematical functions defined by the C standard.

FUNCTIONS
    acos(...)
        acos(x)
        
        Return the arc cosine (measured in radians) of x.
    
    acosh(...)
        acosh(x)
        
        Return the inverse hyperbolic cosine of x.
    
    asin(...)
        asin(x)
        
        Return the arc sine (measured in radians) of x.
    
    asinh(...)
        asinh(x)
        
        Return the inverse hyperbolic sine of x.
    
    atan(...)
        atan(x)
        
        Return the arc tangent (measured in radians) of x.
    
    atan2(...)
        atan2(y, x)
        
        Return the arc tangent (measured in radians) of y/x.
        Unlike atan(y/x), the signs of both x and y are considered.
    
    atanh(...)
        atanh(x)
        
        Return the inverse hyperbolic tangent of x.
    
    ceil(...)
        ceil(x)
        
        Return the ceiling of x as an Integral.
        This is the smallest integer >= x.
    
    copysign(...)
        copysign(x, y)
        
        Return a float with the magnitude (absolute value) of x but the sign 
        of y. On platforms that support signed zeros, copysign(1.0, -0.0) 
        returns -1.0.
    
    cos(...)
        cos(x)
        
        Return the cosine of x (measured in radians).
    
    cosh(...)
        cosh(x)
        
        Return the hyperbolic cosine of x.
    
    degrees(...)
        degrees(x)
        
        Convert angle x from radians to degrees.
    
    erf(...)
        erf(x)
        
        Error function at x.
    
    erfc(...)
        erfc(x)
        
        Complementary error function at x.
    
    exp(...)
        exp(x)
        
        Return e raised to the power of x.
    
    expm1(...)
        expm1(x)
        
        Return exp(x)-1.
        This function avoids the loss of precision involved in the direct evaluation of exp(x)-1 for small x.
    
    fabs(...)
        fabs(x)
        
        Return the absolute value of the float x.
    
    factorial(...)
        factorial(x) -> Integral
        
        Find x!. Raise a ValueError if x is negative or non-integral.
    
    floor(...)
        floor(x)
        
        Return the floor of x as an Integral.
        This is the largest integer <= x.
    
    fmod(...)
        fmod(x, y)
        
        Return fmod(x, y), according to platform C.  x % y may differ.
    
    frexp(...)
        frexp(x)
        
        Return the mantissa and exponent of x, as pair (m, e).
        m is a float and e is an int, such that x = m * 2.**e.
        If x is 0, m and e are both 0.  Else 0.5 <= abs(m) < 1.0.
    
    fsum(...)
        fsum(iterable)
        
        Return an accurate floating point sum of values in the iterable.
        Assumes IEEE-754 floating point arithmetic.
    
    gamma(...)
        gamma(x)
        
        Gamma function at x.
    
    gcd(...)
        gcd(x, y) -> int
        greatest common divisor of x and y
    
    hypot(...)
        hypot(x, y)
        
        Return the Euclidean distance, sqrt(x*x + y*y).
    
    isclose(...)
        isclose(a, b, *, rel_tol=1e-09, abs_tol=0.0) -> bool
        
        Determine whether two floating point numbers are close in value.
        
           rel_tol
               maximum difference for being considered "close", relative to the
               magnitude of the input values
            abs_tol
               maximum difference for being considered "close", regardless of the
               magnitude of the input values
        
        Return True if a is close in value to b, and False otherwise.
        
        For the values to be considered close, the difference between them
        must be smaller than at least one of the tolerances.
        
        -inf, inf and NaN behave similarly to the IEEE 754 Standard.  That
        is, NaN is not close to anything, even itself.  inf and -inf are
        only close to themselves.
    
    isfinite(...)
        isfinite(x) -> bool
        
        Return True if x is neither an infinity nor a NaN, and False otherwise.
    
    isinf(...)
        isinf(x) -> bool
        
        Return True if x is a positive or negative infinity, and False otherwise.
    
    isnan(...)
        isnan(x) -> bool
        
        Return True if x is a NaN (not a number), and False otherwise.
    
    ldexp(...)
        ldexp(x, i)
        
        Return x * (2**i).
    
    lgamma(...)
        lgamma(x)
        
        Natural logarithm of absolute value of Gamma function at x.
    
    log10(...)
        log10(x)
        
        Return the base 10 logarithm of x.
    
    log1p(...)
        log1p(x)
        
        Return the natural logarithm of 1+x (base e).
        The result is computed in a way which is accurate for x near zero.
    
    log2(...)
        log2(x)
        
        Return the base 2 logarithm of x.
    
    modf(...)
        modf(x)
        
        Return the fractional and integer parts of x.  Both results carry the sign
        of x and are floats.
    
    pow(...)
        pow(x, y)
        
        Return x**y (x to the power of y).
    
    radians(...)
        radians(x)
        
        Convert angle x from degrees to radians.
    
    sin(...)
        sin(x)
        
        Return the sine of x (measured in radians).
    
    sinh(...)
        sinh(x)
        
        Return the hyperbolic sine of x.
    
    sqrt(...)
        sqrt(x)
        
        Return the square root of x.
    
    tan(...)
        tan(x)
        
        Return the tangent of x (measured in radians).
    
    tanh(...)
        tanh(x)
        
        Return the hyperbolic tangent of x.
    
    trunc(...)
        trunc(x:Real) -> Integral
        
        Truncates x to the nearest Integral toward 0. Uses the __trunc__ magic method.

DATA
    e = 2.718281828459045
    inf = inf
    nan = nan
    pi = 3.141592653589793
    tau = 6.283185307179586

FILE
    (built-in)


In [15]:
dir(__builtin__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__IPYTHON__', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'display', 'divmod', 'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

Up Next

Built-in data types.