#!/usr/bin/env python
# coding: utf-8
# # Advanced Interactions
#
#
# ### Lambda Functions ###
#
# (anonymous functions)
# from Lisp & functional programming
# In[ ]:
tmp = lambda x: x**2
print(type(tmp))
# In[ ]:
tmp(2)
# In[ ]:
# forget about creating a new function name...just do it!
(lambda x,y: x**2+y)(2,4.5)
# In[ ]:
## create a list of lambda functions
lamfun = [lambda x: x**2, lambda x: x**3, \
lambda y: math.sqrt(y) if y >= 0 else "Really? I mean really? %f" % y]
# In[ ]:
for l in lamfun: print(l(-1.3))
#
# lambda functions are meant to be short, one liners. If you need more complex functions, probably better just to name them
#
# In[ ]:
# %load airline.py
airports = {"DCA": "Washington, D.C.", "IAD": "Dulles", "LHR": "London-Heathrow", \
"SVO": "Moscow", "CDA": "Chicago-Midway", "SBA": "Santa Barbara", "LAX": "Los Angeles",\
"JFK": "New York City", "MIA": "Miami", "AUM": "Austin, Minnesota"}
# airline, number, heading to, gate, time (decimal hours)
flights = [("Southwest",145,"DCA",1,6.00),("United",31,"IAD",1,7.1),("United",302,"LHR",5,6.5),\
("Aeroflot",34,"SVO",5,9.00),("Southwest",146,"CDA",1,9.60), ("United",46,"LAX",5,6.5),\
("Southwest",23,"SBA",6,12.5),("United",2,"LAX",10,12.5),("Southwest",59,"LAX",11,14.5),\
("American", 1,"JFK",12,11.3),("USAirways", 8,"MIA",20,13.1),("United",2032,"MIA",21,15.1),\
("SpamAir",1,"AUM",42,14.4)]
# In[ ]:
help(list.sort)
# In[ ]:
flights.sort(key=lambda x: x[4]) ;
print(flights)
# In[ ]:
import pprint
pprint.pprint(flights)
# ## Multiple column sorting
#
# ```python
# operator.itemgetter(item[, args...])¶
# ```
#
# Return a callable object that fetches item from its operand using the operand’s `__getitem__()` method. If multiple items are specified, returns a tuple of lookup values.
#
# http://docs.python.org/library/operator.html#module-operator
# In[ ]:
import operator
flights.sort(key=operator.itemgetter(4,1,0))
flights
# ### Filter is a certain way to do list comprehension ###
#
# > *filter(function, sequence)* returns a sequence consisting of those items from the sequence for which *function(item)* is true
# In[ ]:
mylist=[num for num in range(101) if (num & 2) and (num & 1) and (num % 11 != 0.0)]
print(mylist)
# In[ ]:
def f(num): return (num & 2) and (num & 1) and (num % 11 != 0.0)
mylist = list(filter(f,range(101)))
print(mylist)
# In[ ]:
mylist = list(map(lambda num: (num & 2) and (num & 1) and (num % 11 != 0.0),range(101)))
print(mylist)
# if the input is a string, so is the output...
# In[ ]:
## also works on strings...try it with lambdas!
import string
a="Charlie Brown said \"!@!@$@!\""
"".join([c for c in a if c in string.ascii_letters])
# In[ ]:
", ".join([str(num) for num in range(101) if (num & 2) and \
(num & 1) and (num % 11 != 0.0)])
# [back]
# ### Map is just another way to do list comprehension ###
# In[ ]:
def timesthree(x): return x*3
list(map(timesthree,"spam"))
# In[ ]:
list(map(lambda x: x**3, range(1,10)))
# ### Reduce returns one value ###
#
# reduce(function, sequence) returns a single value constructed by calling the binary function on the first two items of the sequence, then on the result and the next item, and so on
# In[ ]:
from functools import reduce
# sum from 1 to 10
reduce(lambda x,y: x + y, range(1,11))
get_ipython().run_line_magic('timeit', 'reduce(lambda x,y: x + y, range(1,11))')
# In[ ]:
reduce(lambda x,y: x + y, range(11,1,-1))
# In[ ]:
list(range(11,1,-1))
# In[ ]:
a = ["a","b"]
# In[ ]:
get_ipython().run_line_magic('pinfo', 'reduce')
# In[ ]:
# sum() is a built in function...it’s bound to be faster
get_ipython().run_line_magic('timeit', 'sum(range(1,11))')
# ### `zip()` ###
#
# built in function to pairwise concatenate items in iterables into a list of tuples
# In[ ]:
list(zip(["I","you","them"],["=spam","=eggs","=dark knights"]))
# In[ ]:
list(zip(["I","you","them"],["=spam","=eggs","=dark knights"],["!","?","#"]))
# In[ ]:
a = list(zip(["I","you","them"],["=spam","=eggs","=dark knights"],["!","?","hello","blah"]))
# In[ ]:
a[0][1] = "=eggs"
# In[ ]:
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for a,q in zip(questions, answers):
print('What is your %s? It is %s' % (q,a))
# not to be confused with `zipfile` module which exposes file compression
# # try, except, finally
#
# - Billy: Let's keep going with "Airplanes", for \$200.
# - Bobby Wheat: "Airplanes" for \$200: "And what is the Deal With the Black Box?"
# - [ Tommy buzzes in ] Tommy!
# - Tommy: It's the only thing that survives the crash - why don't they build the whole plane out of the Black Box!
#
# http://snltranscripts.jt.org/91/91rstandup.phtml
#
# http://www.nbc.com/saturday-night-live/video/standup-and-win/2868123
#
# ### Wrap volatile code in try/except/finally
#
# instead of ...
# In[ ]:
tmp = input("Enter a number and I'll square it: ") ; print(float(tmp)**2)
# do this...
# In[ ]:
def f():
try:
tmp = input("Enter a number and I'll square it: ")
print(float(tmp)**2)
except:
print("dude. I asked you for a number and %s is not a number." % tmp)
finally:
print("thanks for playing!")
# In[ ]:
f()
# #### Wrap volatile code in try/except/finally
#
# ```python
# try:
# # volatile stuff here
# tmp = raw_input("Enter a number “ + \
# and I'll square it: ")
# print(float(tmp)**2)
# except:
# # upon error, jump here inside except and execute that code
# print("dude. I asked you for a number and " + \
# "%s is not a number." % tmp)
# finally:
# # regardless of whether you hit an error, execute everything inside the finally block
# print("thanks for playing!")
# ```
#
# In[ ]:
try:
print("eat at" % joes)
finally:
print("bye.")
# - errors in Python generate what are called “exceptions”
# - exceptions can be handled differently depending on what kind of exception they are (we’ll see more of that later)
# - except “catches” these exceptions
# - you do not have to catch exceptions (try/finally) is allowed. Finally block is executed no matter what!
# # exec & eval
#
# `exec` is a statement which executes strings as if they were Python code
# In[ ]:
a = "print('checkit')"
print(a)
# In[ ]:
exec(a)
# In[ ]:
a = "x = 4.56"
# In[ ]:
exec(a)
# In[ ]:
print(x)
# In[ ]:
exec("del x")
# In[ ]:
print(x)
# - dynamically create Python code (!)
# - execute that code w/ implications for current namespace
# In[ ]:
import math
while True:
bi = input("what built in function would you like me to coopt? ")
if bi in ('?',"",'end'):
break
nn = input("what new name would you like to give it? ")
exec("%s = %s" % (nn,bi))
# In[ ]:
jsin(math.pi/2)
# `eval` is an expression which evaluates strings as Python expressions
# In[ ]:
x = eval('5') ; print(x) # x <- 5
x = eval('%d + 6' % x) ; print(x) # x <- 11
x = eval('abs(%d)' % -100) ; print(x) # x <- 100
# In[ ]:
eval('if 1: x = 4') # INVALID; if is a statement, not an expression.
# # Breakout
#
# Write a code which generates python code that approximates the function:
# $$x^2 + x$$
#
# hints:
#
# - randomly generate `lambda` functions using a restricted vocabulary:
# `voc =["x","x"," ","+","-","*","/","1","2","3"]`
#
# - evaluate these `lambda` functions at a fix number of x values and save the difference between those answers and `x**2 + x`
#
# - catch errors!
#
# - start with a file like:
#
# ```python
# import random
# import numpy
#
# voc =["x","x"," ","+","-","*","/","1","2","3"]
#
# nfunc = 1000000
# maxchars = 10 # max how many characters to gen
# eval_places = numpy.arange(-3,3,0.4)
# sin_val = eval_places**2 + eval_places
# tries = []
# for loop...
# ```
#
# In[ ]: