What can sequences do ? List Comprehensions
Select • i-th element: s[i] A cleaner, nicer way to do map-like operations • subsequence (“slice”): s[i:j] >>> [ x*x for x in range(10)] Update -- For mutable sequences (e.g. Lists) [0,1,4,9,16,25,36,49,64,81] • Update i-th element: s[i] = e >>> [2*x for x in “yogurt cheese”] • Update subsequence: s[i:j] = e [“yy”,”oo”,”gg”,”uu”,”rr”,”tt”,…] Member: x in s Iteration: for x in s:
map,filter,reduceList Comprehensions List Comprehensions
Syntax: >>> [ex for x in s] Syntax: >>> [ex for x in s]
Equivalent to: Equivalent to: >>> def map_fn(x): return ex >>> map(map_fn, s)
List Comprehensions List Comprehensions
A cleaner, nicer way to do map+filter-like operations
>>> [ x*x for x in range(10) if even(x)] [0,4,16,36,64] Syntax: >>> [ex for x in s if cx ] >>> [ 2*x for x in “0123456” if even(x)] [“00”,“22”,“44”,“66”] Equivalent to: >>> [z[0] for z in craigslist if z[1]<3.0] [“dinosaur”]
1 List Comprehensions List Comprehensions
Can “nest” the for to iterate over multiple sequences
>>>[(x,y) for x in range(3) for y range(3)]
Syntax: >>> [ex for x in s if cx ] [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2),(2,0),(2, 1),(2,2)] Equivalent to: >>>[(x,y) for x in range(3) for y in range(3) if x > y] >>> def map_fn(x): return e x [(1,0),(2,0),(2,1)] >>> def filter_fn(x): return cx >>> map(map_fn, filter(filter_fn, s))
What can sequences do ? Quicksort in Python
Select def sort(L): • i-th element: s[i] if L==[]: return L • subsequence (“slice”): s[i:j] else: Update -- For mutable sequences (e.g. Lists) l=sort(...) • Update i-th element: s[i] = e r=sort(...) • Update subsequence: s[i:j] = e return(l+L[0:1]+r) Member: x in s Iteration: for x in s:
map,filter,reduceComprehensions: [ex for x in s if cx]
Quicksort in Python Today: Revisit some objects def sort(L): • Exploit features and build powerful if L==[]: return L expressions else: l=sort([x for x in L[1:] if x < L[0]]) Base: int, float, complex r=sort([x for x in L[1:] if x >= L[0]]) return(l+L[0:1]+r) Sequence: string, tuple, list
Maps (Dictionary): key → value
2 Key data structure: Dictionaries Using Dictionaries
Associative arrays, Hash tables … Unsorted list of key,value pairs
Empty Dictionary: {} A table storing a set of “keys”, And a “value” for each key. Non-empty Dictionary: {k1:v1,k2:v2,…}
Any (immutable) object can be a key! Membership: is k in dict: k in d
• int,float,string,tuples… Lookup value of key: d[k]
Very useful! Set value of key: d[k]=v
Dictionaries Dictionaries
>>> d={} def freq(s): def plotfreq(s): d={} d=freq(s) >>> d=dict(mexmenu) for c in s: for k in d.keys(): >>> d[“ceviche”] = 3.95 if c in d: d[c]+=1 print k, “*”*d[k] >>> d else: d[c]=1 {…} return d
>>> d[“burrito”] >>> d=plotfreq([1,1,3.0,”A”,3.0,”A”,”A”,1,2,3.0,1,”A”]) 3.50 >>> d >>> d.keys() … … >>> d = plotfreq(“avrakedavra”) >>> d.keys() >>> d.values() >>> d …
>>> f = open(“foo.txt”,”read”) >>> f.readlines() … >>> for l in f.readlines():
>>> f.close
You now know enough to do PA5 • Python Tutorial: How to open files, read lines • Use the help command • Document every function: What does it do ?
3 Next: What’s in a name ? What’s in a name ?
More precisely: • How should programmer think of data ML (or Functional Languages) • What does a variable “x” really mean ? • Name refers to a Value • Binding maps Names to Values • Environment list of bindings • Environment can be extended • Environment can’t be changed
Data model in functional PL Data model in OO langs
• Vars = names in phonebook • Variables “point to” objects • Evaluation = Most recent • Environment “frozen” in function value • Objects = boxes with data inside – behavior of function cannot be changed – easier reasoning X “pumpkin”
Y 3.142
Z [1,2,3]
Namespaces Ok, but what IS a namespace ?
• Manage variable names in Python A mapping from names to objects
• Similar to, but different from Environments – Core PL concept, unifies many ideas X “pumpkin” Y 3.142 • We will see very important differences Z [1,2,3]
4 Namespaces vs. Environments 1. Assignment
Both are maps from variables to something Basic operation in Imperative PL:
Namespace Environment x = e
What’s the difference ? 1. Compute object corresponding to e 1. Assignment 2. Change the name “x” to refer to object 2. Updates/Mutation
Simple example Simple example i,s = 0,0 i,s = 0,0 while (i <= 3): while (i <= 3): i,s = i+1, s+i i,s = i+1, s+i
Same name “s” - points to different objects - namespace is not extended
1. Assignment 2. Update/Mutation Change what’s inside the box (object) Basic operation in Imperative PL: - Not with immutable objects x = e - eg. integers - But with mutable objects 1. Compute object corresponding to e - eg. arrays, lists, dictionaries 2. Change the name “x” to refer to object >>> x = [100,200] >>> x How is it different from [100, 200] “build a new box with Assignment: changes box that name refers to >>> x[0] = "gobble gobble" updated value inside” ? >>> x ['gobble gobble', 200]
5 Aliasing Aliasing
Two or more names refer to same object Two or more names refer to same object X
>> x = [100,200] [100,200] “Peter Parker” >> y = x Y
“Spider-Man”
Aliasing and Update Aliasing
Two or more names refer to same object Two or more names refer to same object X X
[‘gobble…’,200] [100,200] [‘gobble…’,200] [100,200] >> x = [100,200] >> x = [100,200] >> y = x Y >> y = x Y
>> y[0] = “gobble gobble" >> y[0] = “gobble gobble" >> x >> x [‘gobble gobble’,200] If multiple names refer to same object, update affects values of all names
Aliasing Aliasing
Does not happen in Ocaml/Functional PLs Good because ? • actually it does happen (where ?) • but not exposed to the (130) programmer
Does happen in every imperative PL Bad because ? • Java, Python: names point to objects • C: names point to memory cells
6 Namespaces everywhere Creating Namespaces
Namespace = map from names to objects a.py X 22 a x = 22 y = “this sentence is false” “this…” Notion of namespace pervades Python Y
• Can create namespace, b.py X “pumpkin” • Can name a namespace, x = “pumpkin” y = 3.142 • Can peep inside a namespace (see whats bound) Y 3.142 b
>>> import a Go to code! >>> a.x 22
Namespaces Namespaces
For two namespaces a , b: X a X 22 a • names inside unrelated “this…” “this…” Y • names in different spaces Y “22 pumpkins” a.x : attribute/name “x” in space “a” X X “pumpkin” b.x : Y 3.142 3.142 b attribute/name “x” in space “a” Y b
Different names can point to same object! Different names can point to same object!
Creating Namespaces: Fun Calls Creating Namespaces: Fun Calls
x = 10 X 10 x = 10 X 10
f(x) f(x) f(x) f(x) globals Call-by-Value: globals Questions: • New local namespace for call • Why “new local namespace” (not just stack) ? • y bound to same object (value) as arg x • What’s the deal with “x” not declared/bound in “f” ? • x binding unchanged by call • When do we need to freeze a namespace ? In this case, after call, local namespace disappears…
7 Creating Namespaces: Fun Calls 2 Creating Namespaces: Fun Calls 3
y = 0 len
5 f(5) y z 6 What happened ? Static Scoping f(5) Looks for “n” at run-time ,when “g” is called Lookup at runtime Can’t find “n” in local, global, builtins globals Not compile time Throws run-time error… Missing z added builtins
Creating Namespaces: Fun Calls 3 Aaargh!
>>> def g(y): >>> def g(y): >>> return y + n >>> def return g(y): y + n >>> g(5) >>> g(5) return y + n Changed behavior after definition NameError… NameError… >>> g(5) whether or not fun works depends >>> n = 10 NameError>>> n = 10… on what we did after fundef >>> g(5) >>> g(5)n = 10 15 >>>15 g(5) 15>>> n = 100 Change I/O behavior too … What happened ? >>> g(5) Unlike ML, no new binding: Looks for “n” at run-time ,when “g” is called 105 just change what “n” is bound to Finds “n” in global, returns 15 be careful with free variables! Here “n” is a “free variable” of “g” Needs to be “bound” in some enclosing scope
Python tries to avoid “overwrites” Python tries to avoid “overwrites”
>>> n Python tries to ensure you >>> n Python tries to ensure you 100 don’t overwrite outer variables 100 don’t overwrite outer variables >>> def f(): >>> def f(): >>> n = “smash” >>> n = “smash” >>> print n >>> print n How ? >>> >>> - unlike C/Java >>> f() >>> f() - assignment different from reads smash smash - no variable “declarations” >>> n >>> n 100 100 - assignment = declaration!
8 Python tries to avoid “overwrites” Python tries to avoid “overwrites”
Assignment Revisited >>> n 100 >>> def f(): x = e >>> global n = “smash” >>> print n >>> 1. Compute object corresponding to e >>> f() 2. Change the name “x” to refer to object in smash >>> n the current namespace (added if missing) smash
What happens ? What happens ?
>>> x = 10 >>> x = 10 >>> def g(): >>> def g(): >>> x = x + 1 >>> global x >>> print x >>> x = x + 1 >>> >>> print x >>> g() >>> >>> x >>> g() >>> x
What happens ? What happens ?
>>> x = [10] >>> x = [10] >>> def f(y): >>> def g(): >>> def h(z): >>> x[0] = “abc” >>> return (y+x[0]+z) >>> print x >>> return h >>> >>> >>> g() >>> foo = f(5) >>> x >>> foo
9