[Edu-sig] teaching Python 3.5 in 2016: snapshot

kirby urner kirby.urner at gmail.com
Thu Jul 21 17:02:51 EDT 2016


My "arc" (trajectory) for teaching Python is something like:

>>> dir()
>>> dir(__builtins__)
>>> type(3)
>>> type('A')
>>> import math

... using Python as a calculator and wordprocessor, including file i/o
(open, close, 'r' 'w' 'a')

>>> list, tuple, dict
>>> immutability vs. mutability, explaining how ([], []) is an immutable
"containing" mutables.
>>> import collections.namedtuple

... dot notation access to Atom(protons=, symbol=, long_name=, mass=)

talk about APIs as:  car dashboard (driverless car controversies); web APIs
(point
to API companies like Apigee, Google, programmable web).  Linking
Object.verb()
and Object.noun to API concept also (docstrings = owner's manual / user's
manaul
-- but not a repair manual, which is for #comments in source code and
tests).

tell stories about Browser Wars, emergence of browser as universal client,
HTTP as API, RESTful vs SOAP web services, play with existing APIs that
return JSON

>>> string formatting with new mini-language feature set
>>> def function() notation, arguments vs parameters *args, **kwargs as
either
>>> save function objects to a list, show functions as top-level, lambda
syntax
>>> class Element: that mimics namedtuple Atom. Compare side-by-side
>>> composer.py  (introduce operator overloading)

now show how "namedtuple" API may be duplicated using __getitem__

>From here on, we're prepared to use special names (or "__ribs__" as I
sometimes
call them) as a way to talk about APIs.

E.g.

* the iterator protocol around __next__ and __iter__ may now be presented
using classes.
* Context managers (__enter__, __exit__)
* Descriptors (__set__ and __get__)

We'll get to some of these below, after decorator syntax...

>>> inheritance, MRO (method resolution order)
>>> old fashioned menu-driven API based in input() to do CRUD against
all_elements

# <--- this is where I'm at in the current 5-week course I'm teaching

>>> annotations

What I call "grand unification" is up ahead where we show how a context
manager
mayb be built with generator as a decorator.

Haven't gotten there yet with this class. That's almost black belt, like
maybe brown.

====

Looking ahead to tonight's class, reviewing the bridge we've just crossed...

# -*- coding: utf-8 -*-
"""
Created on Thu Jul 21 12:47:03 2016

@author: Kirby Urner

side-by-side namedtuple and class

Atom (namedtuple) and Element (a non-builtin class) work
as clones of one another, meaning the loader function
and reporting function are agnostic as to which type to
use when building all_elements, a global dictionary of
Periodic Table information.
"""

from collections import namedtuple
import json

Atom = namedtuple("Atom", "protons symbol long_name mass series")

# imagine
# http://inventory.earth/elements?symbol="He"
# pulling from a DB

# using a 'rich data structure'
# http://grokbase.com/t/python/edu-sig/0676rrx2n0/rich-data-structure
# https://mail.python.org/pipermail/edu-sig/2006-June/006609.html

json_data = """{
    "He": [2, "He", "Helium", 4.002602, "Nobel gas"],
    "C": [6, "C", "Carbon", 12.0107, "Noble gas"],
    "Na": [11, "Na", "Sodium", 22.98976928, "Alkali metal"],
    "H": [1, "H", "Hydrogen", 1.00794, "Other nonmetal"],
    "Ne": [10, "Ne", "Neon", 20.1797, "Noble gas"],
    "Si": [14, "Si", "Silicon", 28.0855, "Metalloid"],
    "Li": [3, "Li", "Lithium", 6.941, "Alkali metnal"],
    "F": [9, "F", "Fluorine", 18.9984032, "Metalloid"],
    "Be": [4, "Be", "Beryllium", 9.012182, "Alkaline earth metal"],
    "O": [8, "O", "Oxygen", 15.9994, "Other nonmetal"],
    "Mg": [12, "Mg", "Magnesium", 24.3050, "Alkaline earth metal"],
    "Al": [13, "Al", "Aluminum", 26.9815386, "Post-transition metal"],
    "N": [7, "N", "Nitrogen", 14.0067, "Other nonmetal"],
    "B": [5, "B", "Boron", 10.811, "Metalloid"]
}"""

class Element:
    fields = "protons symbol long_name mass series"
    repstr = ("Atom(protons={protons}, symbol='{symbol}', "
    "long_name='{long_name}', "
    "mass={mass}, series='{series}')")

    def __init__(self, protons: int, symbol: str,
                 long_name: str, mass: float, series: str):
        # build self.__dict__
        self.protons = protons
        self.symbol = symbol
        self.long_name = long_name
        self.__dict__['mass'] = mass # same idea
        self.series = series

    def __getitem__(self, idx):
        return self.__dict__[self.fields[idx]]

    def __repr__(self):
        return self.repstr.format(**self.__dict__)


def loader(target):
    """
    create a dict all_elements of either:
       target = "tuples"    : namedtuples of type Atom or...
       target = "instances" : instances of Element class
    """
    global all_elements
    all_elements = {}
    the_dict = json.loads(json_data)  # json_data is a global
    for key, value in the_dict.items():
        if target == "tuples":
            all_elements[key] = Atom(*value) # explode list object
        if target == "instances":
            all_elements[key] = Element(*value) # explode list
object

def print_periodic_table():
    """
    sort all_elements by number of protons, ordered_elements local only
    What about series?
    """
    ordered_elements = sorted(all_elements.values(), key = lambda k:
k.protons)

    print("PERIODIC TABLE OF THE ELEMENTS")
    print("-" * 70)
    print("Symbol |Long Name             |Protons |Mass   |Series  " )
    print("-" * 70)

    for the_atom in ordered_elements:
        print("{:6} | {:20} | {:6} | {:5.2f} |
{:15}".format(the_atom.symbol,
                          the_atom.long_name,
                          the_atom.protons,
                          the_atom.mass,
                          the_atom.series))


if __name__ == "__main__":
    # loader("tuples")
    loader("instances")
    print_periodic_table()

OUTPUT in REPL:

>>> boron = all_elements["B"]

>>> type(boron)
__main__.Element

>>> boron
Atom(protons=5, symbol='B', long_name='Boron', mass=10.811,
series='Metalloid')

>>> print_periodic_table()

PERIODIC TABLE OF THE ELEMENTS
----------------------------------------------------------------------
Symbol |Long Name             |Protons |Mass   |Series
----------------------------------------------------------------------
H      | Hydrogen             |      1 |  1.01 | Other nonmetal
He     | Helium               |      2 |  4.00 | Nobel gas
Li     | Lithium              |      3 |  6.94 | Alkali metnal
Be     | Beryllium            |      4 |  9.01 | Alkaline earth metal
B      | Boron                |      5 | 10.81 | Metalloid
C      | Carbon               |      6 | 12.01 | Noble gas
N      | Nitrogen             |      7 | 14.01 | Other nonmetal
O      | Oxygen               |      8 | 16.00 | Other nonmetal
F      | Fluorine             |      9 | 19.00 | Metalloid
Ne     | Neon                 |     10 | 20.18 | Noble gas
Na     | Sodium               |     11 | 22.99 | Alkali metal
Mg     | Magnesium            |     12 | 24.30 | Alkaline earth metal
Al     | Aluminum             |     13 | 26.98 | Post-transition metal
Si     | Silicon              |     14 | 28.09 | Metalloid
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/edu-sig/attachments/20160721/5b9b707f/attachment.html>


More information about the Edu-sig mailing list