Python boots up with builtins already in the namespace and checked as a part of the name resolution protocol...
Using difference slices, we an check portions of a long list.
In [1]:
from pprint import pprint
# I, Python am built from types, such as builtin types:
the_builtins = dir(__builtins__) # always here
pprint(the_builtins[-10:]) # no need to import
Lets check our understanding that the native types -- the ones we count on to build more complex types -- live in builtins:
In [2]:
for the_string in ["list", "tuple", "dict", "int", "float"]:
if the_string in the_builtins:
print("Yes I am a native type: ", the_string)
assert type(eval(the_string)) == type # all types in this club
else:
print("No, I'm not native: ", the_string)
And now for something completely different, lets define a class that does substitution based on a permutation of lower-case ascii letters plus space. Such a type is given more substantial implementation in the form of our px_class.py, which allows permutations to multiply, giving more permuations.
In [3]:
# usually up top
from string import ascii_lowercase as all_lowers
from random import shuffle
class P:
"""
class Px is the more sophisticated version of this class
"""
def __init__(self, p=None):
if not p:
original = all_lowers + ' '
scrambled = list(original)
shuffle(scrambled)
self.perm = dict(zip(original, scrambled))
else:
self.perm = p
def __invert__(self):
"""reverse my perm, make a new me"""
reverse = dict(zip(self.perm.values(), self.perm.keys()))
return P(reverse) # <-- new P instance
def encrypt(self, s):
output = ""
for c in s:
output += self.perm[c]
return output
def decrypt(self, s):
rev = ~self # <-- new P instance
return rev.encrypt(s) # <-- symmetric key
p = P()
m = "i like python so much because it does everything" # palindrome
c = p.encrypt(m)
print(m) # plaintext
print(c) # ciphertext
d = p.decrypt(c)
print(d)
In the code below, we use a context manager to connect and disconnect from a SQLite database. The context manager is developed from a simple generator with precisely one yield statement, using the @contextmanager decorator.
In [4]:
import sqlite3 as sql
import os.path
import json
import time
from contextlib import contextmanager
PATH = "/Users/kurner/Documents/classroom_labs/session10"
DB1 = os.path.join(PATH, 'periodic_table.db')
def mod_date():
return time.mktime(time.gmtime()) # GMT time
@contextmanager
def Connector(db):
try:
db.conn = sql.connect(db.db_name) # connection
db.curs = db.conn.cursor() # cursor
yield db
except Exception as oops:
if oops[0]:
raise
db.conn.close()
class elemsDB:
def __init__(self, db_name):
self.db_name = db_name
def seek(self, elem):
if self.conn:
if elem != "all":
query = ("SELECT * FROM Elements "
"WHERE elem_symbol = '{}'".format(elem))
self.curs.execute(query)
result = self.curs.fetchone()
if result:
return json.dumps(list(result))
else:
query = "SELECT * FROM Elements ORDER BY elem_protons"
self.curs.execute(query)
result={}
for row in self.curs.fetchall():
result[row[1]] = list(row)
return json.dumps(result)
return "NOT FOUND"
At this point, we're able to seek a specific row from the Elements table, or request all of them. In a Flask web application, the controlling argument might come from a GET request, i.e. a URL such as /api/elements?elem=H
In [7]:
output = ""
with Connector(elemsDB(DB1)) as dbx:
output = dbx.seek("C")
print(output)
To be continued...
In [9]:
import requests
data = {}
data["protons"]=100
data["symbol"]="Kr"
data["long_name"]="Kirbium"
data["mass"]=300
data["series"]="Dunno"
data["secret"]="DADA" # <--- primitive authentication
the_url = 'http://localhost:5000/api/elements'
r = requests.post(the_url, data=data)
print(r.status_code)
print(r.content)