Slide conversion: https://echorand.me/presentation-slides-with-jupyter-notebook.html

`$ jupyter-nbconvert --to slides slides.ipynb --reveal-prefix=reveal.js --post serve`

# A Brief Python Introduction¶

Keith Maull
Jan. 03, 2019

## Python is a general purpose programming language that is ...¶

- interpreted
- dynamically typed (not statically typed)
- intuitive
- fun and addictive

### strongly typed¶

- So to answer your question: another way to look at this that's mostly correct is to say that static typing is compile-time type safety and strong typing is runtime type safety. ### everything is an object

## Python syntax can be learned very quickly¶

- indentation matters
- there are no curly braces, semicolons or tricks ...
- the syntax is one of the true joys of the language once you learn not to fight it

## We will learn 80% of the syntax today in 1 hour!¶

In [1]:

    a_simple_list = ['a', 'b', 'c', 'd']
    if a_simple_list[0] == 'a':
        print("The first item of the list is an `a`")

    The first item of the list is an `a`

In [2]:

    for item in a_simple_list:
        print(item)

    a
    b
    c
    d

In [3]:

    count = 0
    while (count < 5):
        print(count)
        count+=1

    0
    1
    2
    3
    4

In [4]:

    # functions are easy
    def my_func(x, y):
        return x*y

    my_func(3,4)

Out[4]:

    12

### x, y = y, x¶

## Python has many modules (aka "libraries") that do fun things¶

In [5]:

    # random numbers generator
    import random
    print(random.randint(0,100))

    89

In [6]:

    # http library
    import requests
    r = requests.get("https://raw.githubusercontent.com/atebits/Words/master/Words/en.txt")
    if r.status_code == 200:
        data = r.text
        print(data[:1000])

    aa
    aah
    aahed
    aahing
    aahs
    aal
    aalii
    aaliis
    aals
    aardvark
    aardvarks
    aardwolf
    aardwolves
    aargh
    aarrgh
    aarrghh
    aarti
    aartis
    aas
    aasvogel
    aasvogels
    ab
    aba
    abac
    abaca
    abacas
    abaci
    aback
    abacs
    abacterial
    abactinal
    abactinally
    abactor
    abactors
    abacus
    abacuses
    abaft
    abaka
    abakas
    abalone
    abalones
    abamp
    abampere
    abamperes
    abamps
    aband
    abanded
    abanding
    abandon
    abandoned
    abandonedly
    abandonee
    abandonees
    abandoner
    abandoners
    abandoning
    abandonment
    abandonments
    abandons
    abandonware
    abandonwares
    abands
    abapical
    abas
    abase
    abased
    abasedly
    abasement
    abasements
    abaser
    abasers
    abases
    abash
    abashed
    abashedly
    abashes
    abashing
    abashless
    abashment
    abashments
    abasia
    abasias
    abasing
    abask
    abatable
    abate
    abated
    abatement
    abatements
    abater
    abaters
    abates
    abating
    abatis
    abatises
    abator
    abators
    abattis
    abattises
    abattoir
    abattoirs
    abattu
    abature
    abatures
    abaxial
    abaxile
    abaya
    abayas
    abb
    abba
    abbacies
    abbacy
    abbas
    abbatial
    abbe
    abbed
    abbes
    abbess
    abbesses
    abbey
    abbeys
    abbot
    abbotcies
    abbotcy
    abbots
    abbotship
    abbotsh

## And a strength of the language is text processing ...¶

In [7]:

    data.split('\n')[:10]

Out[7]:

    ['aa',
     'aah',
     'aahed',
     'aahing',
     'aahs',
     'aal',
     'aalii',
     'aaliis',
     'aals',
     'aardvark']

In [8]:

    top_100_five_letter_words = []

    for w in data.split('\n'):
        if len(w) == 5:
            top_100_five_letter_words.append(w)
        if len(top_100_five_letter_words) == 100:
            break

    print(top_100_five_letter_words)

    ['aahed', 'aalii', 'aargh', 'aarti', 'abaca', 'abaci', 'aback', 'abacs', 'abaft', 'abaka', 'abamp', 'aband', 'abase', 'abash', 'abask', 'abate', 'abaya', 'abbas', 'abbed', 'abbes', 'abbey', 'abbot', 'abcee', 'abeam', 'abear', 'abele', 'abets', 'abhor', 'abide', 'abies', 'abled', 'abler', 'ables', 'ablet', 'ablow', 'abmho', 'abode', 'abohm', 'aboil', 'aboma', 'aboon', 'abord', 'abore', 'abort', 'about', 'above', 'abram', 'abray', 'abrim', 'abrin', 'abris', 'absey', 'absit', 'abuna', 'abune', 'abuse', 'abuts', 'abuzz', 'abyes', 'abysm', 'abyss', 'acais', 'acari', 'accas', 'accoy', 'acerb', 'acers', 'aceta', 'achar', 'ached', 'aches', 'achoo', 'acids', 'acidy', 'acing', 'acini', 'ackee', 'acker', 'acmes', 'acmic', 'acned', 'acnes', 'acock', 'acold', 'acorn', 'acred', 'acres', 'acrid', 'acted', 'actin', 'acton', 'actor', 'acute', 'acyls', 'adage', 'adapt', 'adaws', 'adays', 'addax', 'added']

In [9]:

    top_100_five_letter_words_ending_in_g = []

    for w in data.split('\n'):
        if len(w) == 5 and w[-1] is 'g':
            top_100_five_letter_words_ending_in_g.append(w)
        if len(top_100_five_letter_words_ending_in_g) == 100:
            break

    print(top_100_five_letter_words_ending_in_g)

    ['acing', 'aging', 'ahing', 'aking', 'alang', 'almug', 'along', 'among', 'aping', 'awing', 'axing', 'befog', 'being', 'bewig', 'bhang', 'bling', 'boing', 'boong', 'bourg', 'bring', 'brung', 'chang', 'clang', 'cling', 'clung', 'cohog', 'colog', 'craig', 'cuing', 'debag', 'debug', 'defog', 'derig', 'doing', 'droog', 'duing', 'dwang', 'dying', 'ehing', 'eking', 'embog', 'emong', 'ennog', 'ering', 'exing', 'eying', 'fling', 'flong', 'flung', 'glogg', 'going', 'gulag', 'hoing', 'hying', 'hyleg', 'icing', 'incog', 'iring', 'kaing', 'kiang', 'klang', 'klieg', 'klong', 'krang', 'kreng', 'kyang', 'liang', 'lolog', 'lying', 'moong', 'nying', 'obang', 'oflag', 'ohing', 'oping', 'orang', 'owing', 'phang', 'piing', 'pirog', 'pling', 'plong', 'prang', 'prong', 'rejig', 'renig', 'repeg', 'rerig', 'retag', 'rolag', 'ruing', 'scoog', 'scoug', 'scrag', 'scrog', 'shrug', 'skegg', 'slang', 'sling', 'slung']

### json support is excellent (as it should be)¶

In [10]:

    import json
    import requests

    r = requests.get("https://raw.githubusercontent.com/LearnWebCode/json-example/master/pets-data.json")
    if r.status_code == 200:
        pet_data = json.loads(r.text)
    print(data)

    IOPub data rate exceeded.
    The notebook server will temporarily stop sending output
    to the client in order to avoid crashing it.
    To change this limit, set the config variable
    `--NotebookApp.iopub_data_rate_limit`.

    Current values:
    NotebookApp.iopub_data_rate_limit=1000000.0 (bytes/sec)
    NotebookApp.rate_limit_window=3.0 (secs)

In [11]:

    pet_data['pets'][0]

Out[11]:

    {'name': 'Purrsloud',
     'species': 'Cat',
     'favFoods': ['wet food', 'dry food', '<strong>any</strong> food'],
     'birthYear': 2016,
     'photo': 'https://learnwebcode.github.io/json-example/images/cat-2.jpg'}

### Regular expressions ... also very accessible¶

In [12]:

    # regular expressions
    import re
    s = r'^t.*ers$' # all words starting with `t` ending in `ers`

    for w in data.split('\n'):
        if re.match(s, w):
            print(w)

    tabasheers
    tabers
    tabliers
    taborers
    tabourers
    tacheometers
    tachometers
    tachygraphers
    tachymeters
    tackers
    tackifiers
    tacklers
    taggers
    tailenders
    tailers
    tailgaters
    tailwaters
    taivers
    takeovers
    takers
    talebearers
    talers
    talkers
    talliers
    tambers
    tambourers
    tamers
    tamperers
    tampers
    tanagers
    tanglers
    tankbusters
    tankers
    tanners
    tantalisers
    tantalizers
    taperers
    tapers
    tappers
    tapsters
    targeteers
    tarnishers
    tarpapers
    tarriers
    tarsiers
    taseometers
    tasers
    tasimeters
    taskers
    taskmasters
    tastemakers
    tasters
    taters
    tatlers
    tatters
    tattlers
    tattooers
    taunters
    tautomers
    taverners
    tavers
    tawers
    taxameters
    taxers
    taximeters
    taxonomers
    taxpayers
    teachers
    teamakers
    teamers
    teamsters
    tearers
    tearjerkers
    teaselers
    teasellers
    teasers
    teatasters
    tedders
    teemers
    teenagers
    teeners
    teenyboppers
    teers
    teeters
    teethers
    teetotalers
    teetotallers
    telecasters
    telecommuters
    teleconverters
    telegraphers
    telemarketers
    telemeters
    telephoners
    teleprinters
    teletypewriters
    televiewers
    televisers
    teleworkers
    telewriters
    telfers
    tellers
    tellurometers
    telphers
    temperers
    tempers
    temporisers
    temporizers
    tempters
    tenderers
    tenderisers
    tenderizers
    tenderometers
    tenders
    tenners
    tenoners
    tenpounders
    tensimeters
    tensiometers
    tensioners
    tenters
    tentmakers
    termers
    terminers
    terpolymers
    terriers
    terrifiers
    terrorisers
    terrorizers
    testers
    testifiers
    tethers
    tetramers
    tetrameters
    tetters
    teuchters
    texters
    thalers
    thankers
    thanksgivers
    thatchers
    thawers
    theatergoers
    theaters
    theologasters
    theologers
    theologisers
    theologizers
    theorisers
    theorizers
    theosophers
    thermographers
    thermometers
    thickeners
    thiggers
    thillers
    thimbleriggers
    thinkers
    thinners
    thirsters
    thrashers
    threaders
    threadmakers
    threapers
    threateners
    threepers
    threshers
    thrillers
    thrivers
    throbbers
    thronners
    throttlers
    throwers
    throwsters
    thrummers
    thrusters
    thumpers
    thunderers
    thunders
    thundershowers
    thurifers
    thwackers
    thwarters
    tickers
    ticklers
    tiddlers
    tidewaiters
    tidewaters
    tidiers
    tiebreakers
    tiers
    tigers
    tighteners
    tilers
    tillers
    tilters
    tiltmeters
    timbers
    timekeepers
    timepleasers
    timers
    timesavers
    timeservers
    timeworkers
    timoneers
    tinders
    tinglers
    tinkerers
    tinkers
    tinklers
    tinners
    tinters
    tintometers
    tippers
    tipplers
    tipsters
    titers
    titfers
    tithers
    titleholders
    titlers
    titterers
    titters
    toadeaters
    toasters
    toastmasters
    tobogganers
    tochers
    toddlers
    todgers
    toeraggers
    toggers
    togglers
    toilers
    tokers
    tollers
    tolters
    toners
    tongers
    tongsters
    tonguesters
    tonkers
    tonners
    tonometers
    tontiners
    toolers
    toolholders
    toolmakers
    toolpushers
    tooters
    tootlers
    topers
    topliners
    topmakers
    topnotchers
    topographers
    toppers
    topsiders
    torchbearers
    torchers
    torchiers
    tormenters
    torpedoers
    torquers
    torturers
    toshers
    tossers
    totalisers
    totalizers
    toters
    totterers
    totters
    touchers
    touchpapers
    tougheners
    tourers
    tourneyers
    tousers
    touters
    towers
    towsers
    toyers
    tracers
    trackers
    tracklayers
    trackwalkers
    traders
    traditioners
    traducers
    traffickers
    trailblazers
    trailbreakers
    trailers
    trainbearers
    trainers
    trammelers
    trammellers
    trampers
    tramplers
    trampoliners
    tranquilisers
    tranquilizers
    tranquillisers
    tranquillizers
    transceivers
    transcribers
    transducers
    transferrers
    transfers
    transformers
    transfusers
    transgenders
    transhippers
    transmissometers
    transmitters
    transmuters
    transplanters
    transponders
    transporters
    transposers
    transputers
    transshippers
    transvaluers
    transverters
    tranters
    trapanners
    trappers
    trapshooters
    trashers
    travelers
    travellers
    traversers
    trawlers
    treacherers
    treachers
    treaders
    treadlers
    treasurers
    treaters
    treehoppers
    trekkers
    tremblers
    trenchers
    trendsetters
    trepanners
    trephiners
    trespassers
    triaconters
    tribometers
    tributers
    trickers
    tricksters
    tricyclers
    triers
    triflers
    triggers
    trigonometers
    trillers
    trimers
    trimesters
    trimeters
    trimmers
    trinketers
    triphammers
    trippers
    tripplers
    triumphers
    trochanters
    trocheameters
    trochometers
    troffers
    trollers
    tromometers
    troopers
    troposcatters
    trossers
    trotters
    troublemakers
    troublers
    troubleshooters
    trouncers
    troupers
    trousers
    trouters
    trovers
    trowelers
    trowellers
    trowsers
    truckers
    trucklers
    truckmasters
    trudgers
    trumpeters
    truncheoners
    trundlers
    trussers
    trustbusters
    trusters
    tryers
    trysters
    tubbers
    tubers
    tuckers
    tufters
    tuggers
    tumblers
    tummlers
    tuners
    tunnelers
    tunnellers
    turbidimeters
    turbochargers
    turcopoliers
    turners
    turnovers
    turtlers
    tushkers
    tuskers
    tussers
    tutoyers
    tutworkers
    tuyers
    twaddlers
    twangers
    twanglers
    twattlers
    tweakers
    tweedlers
    tweenagers
    tweeners
    tweers
    tweeters
    tweezers
    twicers
    twiddlers
    twiers
    twiggers
    twiners
    twinflowers
    twinklers
    twinters
    twirlers
    twisters
    twitchers
    twitterers
    twitters
    twoccers
    twockers
    twoers
    twofers
    twoseaters
    twyers
    tyers
    tylers
    typecasters
    typefounders
    typesetters
    typewriters
    typifiers
    typographers
    tyrannisers
    tyrannizers

### There are many thousands of libraries to get lost in ...¶

## Data types in Python are simple and complete ...¶

- You are already familiar with these:
  - numbers (`1`, `1.87`, `-0.88`, ...)
  - strings (`"Hello"`, `'Hello'`)
  - Boolean (`True`, `False`)
  - `None`

In [13]:

    ### No surprises here ...

In [14]:

    1 + 2

Out[14]:

    3

In [15]:

    'hello' + "Hello"

Out[15]:

    'helloHello'

## Iterables are an important type category that includes:¶

- lists
- tuples
- sets

### Lists are just like arrays ...¶

In [16]:

    lst = [1, 2, "three"]
    print(lst[1])

    2

In [17]:

    for i in lst:
        print(i, end=" ")

    1 2 three

In [18]:

    lst + ['a', 'b']

Out[18]:

    [1, 2, 'three', 'a', 'b']

### Python doesn't require you to keep up with indices ...¶

- but if you need them (which you rarely will) use `enumerate`

In [19]:

    for idx, l in enumerate(lst):
        print("{}:{}".format(idx, l), end=" ")

    0:1 1:2 2:three

### You can also do cool things with list access ...¶

In [20]:

    lst[-1]

Out[20]:

    'three'

In [21]:

    lst[0:2]

Out[21]:

    [1, 2]

In [22]:

    lst[::-1]

Out[22]:

    ['three', 2, 1]

### Tuples are another useful type¶

- they are just immutable lists
- and denoted `(1, 2, 'three`)

### Sets are also valuable¶

In [23]:

    set([1,1,1,1,1,1,2,3,4,5,5,5,5,5,5,5])

Out[23]:

    {1, 2, 3, 4, 5}

In [24]:

    setA = set([1,2])
    setB = set([1,2,3,4,5])
    setA.union(setB)

Out[24]:

    {1, 2, 3, 4, 5}

In [25]:

    setA.difference(setB)

Out[25]:

    set()

In [26]:

    setB.difference(setA)

Out[26]:

    {3, 4, 5}

In [27]:

    setA.intersection(setB)

Out[27]:

    {1, 2}

## Dictionaries are also a crucial type in the language¶

- associative arrays
- key/value pairs

In [28]:

    d = {"a": 5, "b": 6}
    print(d)

    {'a': 5, 'b': 6}

In [29]:

    d = dict([('a', 5), ('b', 6)])
    print(d)

    {'a': 5, 'b': 6}

### Providing the usual suspects ...¶

In [30]:

    d['a']

Out[30]:

    5

In [31]:

    d.keys()

Out[31]:

    dict_keys(['a', 'b'])

In [32]:

    d.values()

Out[32]:

    dict_values([5, 6])

In [33]:

    for key, value in d.items():
        print("{}=>{}".format(key, value))

    a=>5
    b=>6

## Python logic operators are intuitive¶

- you've seen `in` and `is`
- but there is `not`, `not in`, `is not`, `and`, `or`

In [34]:

    1 is 2

Out[34]:

    False

In [35]:

    1 is not 2

Out[35]:

    True

In [36]:

    True and True

Out[36]:

    True

In [37]:

    True or False

Out[37]:

    True

In [38]:

    False or False

Out[38]:

    False

In [39]:

    False is not True

Out[39]:

    True

In [40]:

    s = 'supercalifragilistic'

In [41]:

    'u' in s

Out[41]:

    True

In [42]:

    'z' not in s

Out[42]:

    True

In [43]:

    lst = ['a', 'b', 1, 2, 3]

In [44]:

    'a' in lst

Out[44]:

    True

In [45]:

    s == 'supercalifragilistic'

Out[45]:

    True

In [46]:

    s is 'supercalifragilistic'

Out[46]:

    True

In [47]:

    lst == ['a', 'b', 1, 2, 3]

Out[47]:

    True

In [48]:

    lst is ['a', 'b', 1, 2, 3]

Out[48]:

    False

## Flow control in Python also includes all the usuals ...¶

- `if/elif/else`
- `for`
- `while`

In [49]:

    s = 'this is a test'

    if s[0] == 't':
        print("the first letter is a 't'")
    else:
        print("the first letter is not a 't'")

    the first letter is a 't'

In [50]:

    for c in s:
        print("{}".format(c))

    t
    h
    i
    s

    i
    s

    a

    t
    e
    s
    t

In [51]:

    # THIS IS NOT PYTHONIC! for is more elegant

    i = 0
    while(i < len(s)):
        print("{}".format(s[i]))
        i+=1

    t
    h
    i
    s

    i
    s

    a

    t
    e
    s
    t

## Python's built in functions are excellent¶

- There are about 69 functions
- some of the most common/useful are:
  - `min`, `max`, `all`, `any`
  - `zip`, `range`, `len`, `map`, `sorted`
  - `reversed`

### Let's play:¶

- PROBLEM: create a 16 character random password of upper, lower and number
- ONE SOLUTION: use what we know about the ASCII table and the `chr()` built in function

HINT 1:

In [52]:

    chr(122)

Out[52]:

    'z'

In [53]:

    import random

    for i in range(0, 17):
        # get a number in the ASCII range
        while(True):
            rnd_c = random.randint(48, 123)
            if rnd_c < 58 or (rnd_c > 65 and rnd_c <91) or (rnd_c > 96 and rnd_c < 123):
                break

        print(chr(rnd_c), end="")

    uMVKgvYyB114e4rpj

## Functions are straightforward and intuitive¶

In [54]:

    def a_function():
        return 1

    a_function()

Out[54]:

    1

### Function arguments (parameters) come in three flavors¶

- positional
- keyword
- mixed

Note: default values are allowed!

In [55]:

    def a_function(a, b, c):
        return a*b*c

    a_function(1,2,3)

Out[55]:

    6

In [56]:

    def a_function(a=1, b=1, c=1):
        return a*b*c

    a_function(a=3,b=8,c=8)

Out[56]:

    192

In [57]:

    a_function(a=4)

Out[57]:

    4

In [58]:

    a_function(3,b=4,c=4)

Out[58]:

    48

In [59]:

    def a_function(a, b=1, c=1):
        return a*b*c

    a_function(6,b=8,c=8)

Out[59]:

    384

In [60]:

    a_function(6, 8, 8)

Out[60]:

    384

### Functions can return multiple values with tuples¶

In [61]:

    def b_function():
        return (1, 2, 3)

In [62]:

    b_function()

Out[62]:

    (1, 2, 3)

In [63]:

    x, y, z = b_function()
    print(x, y, z)

    1 2 3

## Exceptions are valuable for good code!¶

- Python supports `try`/`except`/`finally` and they should be used regularly

In [64]:

    def c_function(a, b, c):
        try:
            if a<0:
                raise Exception
            return a*b*c
        except Exception as e:
            print("The first parameter cannot be less than zero.")
        finally:
            pass # we don't need to clean up anything after the exception

In [65]:

    c_function(-1, 2, 3)

    The first parameter cannot be less than zero.

### What did the function return from the exception???¶

ALL PYTHON FUNCTIONS IMPLICITLY RETURN `None` WHEN NO RETURN VALUE IS SPECIFIED

In [66]:

    c_function(-1, 2, 3) is None

    The first parameter cannot be less than zero.

Out[66]:

    True

## Comprehensions¶

### List comprehensions provide shorthand for building lists¶

In [67]:

    l1 = [x for x in range(0,11)]
    l1

Out[67]:

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

In [68]:

    def pw_generator():
        ascii_pw_range = list(range(48,58)) + list(range(65,91)) + list(range (97, 123))

        return ''.join([chr(random.choice(ascii_pw_range)) \
                        for i in range(0,10)])

    pw_generator()

Out[68]:

    'TMbD0xr0Bj'

In [69]:

    [pw_generator() for i in range(0,15)]

Out[69]:

    ['MIO3ewedYc',
     'YbFp3ofMhC',
     'lgy5GUvod4',
     'VfOjbJ1oF3',
     'tqYltK37KK',
     'E4SzZ0zRjX',
     'fdJRpvyHrn',
     '9cCas9FpyA',
     '33qhlSo7kd',
     'dL1QupAp0V',
     'KBciH7ZSaN',
     '3B1StGRLLe',
     'bR6wZCAzsa',
     '9gq3zcB6lb',
     'vmNodUhosK']

### Dictionary comprehensions are also quite nice ...¶

- Let's say you want to swap the key, value pairs in a dictionary ...

In [70]:

    d1 = dict([('a', 1), ('b', 2), ('c', 3)])
    { v:k for (k,v) in d1.items() }

Out[70]:

    {1: 'a', 2: 'b', 3: 'c'}

- something more practical might be to filter out all values not meeting a criterion

In [71]:

    d1 = dict([('a', 1), ('b', 2), ('c', 3)])
    { v:k for (k,v) in d1.items() if v%2 != 0}

Out[71]:

    {1: 'a', 3: 'c'}

## LET'S PLAY!¶