DevDays Whirlwind Python
Created 7 October 2009
This was a presentation I gave at the DevDays Boston conference in 2009. I don’t have much text to go with it, but these are the slides. If you need them larger, there is a zip file of .pngs.
![Slide 0](http://nedbatchelder.com/text/devdays/devdays_000.png)
![Slide 1](http://nedbatchelder.com/text/devdays/devdays_001.png)
![Slide 2](http://nedbatchelder.com/text/devdays/devdays_002.png)
![Slide 3](http://nedbatchelder.com/text/devdays/devdays_003.png)
![Slide 4](http://nedbatchelder.com/text/devdays/devdays_004.png)
~ Spell corrector ~
Joel’s suggestion was to explain Peter Norvig’s Spell Corrector line-by-line. I’ve made a few small edits for expository purposes.
![Slide 6](http://nedbatchelder.com/text/devdays/devdays_006.png)
![Slide 7](http://nedbatchelder.com/text/devdays/devdays_007.png)
Here’s the code:
import re, collections
def words(text):
return re.findall('[a-z]+', text.lower())
def train(words):
model = collections.defaultdict(int)
for w in words:
model[w] += 1
return model
NWORDS = train(words(file('big.txt').read()))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
def edits1(word):
s = [(word[:i], word[i:]) for i in range(len(word) + 1)]
deletes = [a + b[1:] for a, b in s if b]
transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)>1]
replaces = [a + c + b[1:] for a, b in s for c in alphabet if b]
inserts = [a + c + b for a, b in s for c in alphabet]
return set(deletes + transposes + replaces + inserts)
def known_edits2(word):
return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS)
def known(words):
return set(w for w in words if w in NWORDS)
def correct(word):
candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word]
return max(candidates, key=NWORDS.get)
if __name__ == '__main__':
import sys
for w in sys.argv[1:]:
print "%s -> %s" % (w, correct(w))
![Slide 8](http://nedbatchelder.com/text/devdays/devdays_008.png)
![Slide 9](http://nedbatchelder.com/text/devdays/devdays_009.png)
![Slide 10](http://nedbatchelder.com/text/devdays/devdays_010.png)
![Slide 11](http://nedbatchelder.com/text/devdays/devdays_011.png)
![Slide 12](http://nedbatchelder.com/text/devdays/devdays_012.png)
![Slide 13](http://nedbatchelder.com/text/devdays/devdays_013.png)
![Slide 14](http://nedbatchelder.com/text/devdays/devdays_014.png)
![Slide 15](http://nedbatchelder.com/text/devdays/devdays_015.png)
![Slide 16](http://nedbatchelder.com/text/devdays/devdays_016.png)
![Slide 17](http://nedbatchelder.com/text/devdays/devdays_017.png)
![Slide 18](http://nedbatchelder.com/text/devdays/devdays_018.png)
![Slide 19](http://nedbatchelder.com/text/devdays/devdays_019.png)
![Slide 20](http://nedbatchelder.com/text/devdays/devdays_020.png)
~ Templating ~
![Slide 22](http://nedbatchelder.com/text/devdays/devdays_022.png)
![Slide 23](http://nedbatchelder.com/text/devdays/devdays_023.png)
![Slide 24](http://nedbatchelder.com/text/devdays/devdays_024.png)
![Slide 25](http://nedbatchelder.com/text/devdays/devdays_025.png)
![Slide 26](http://nedbatchelder.com/text/devdays/devdays_026.png)
![Slide 27](http://nedbatchelder.com/text/devdays/devdays_027.png)
![Slide 28](http://nedbatchelder.com/text/devdays/devdays_028.png)
![Slide 29](http://nedbatchelder.com/text/devdays/devdays_029.png)
![Slide 30](http://nedbatchelder.com/text/devdays/devdays_030.png)
![Slide 31](http://nedbatchelder.com/text/devdays/devdays_031.png)
![Slide 32](http://nedbatchelder.com/text/devdays/devdays_032.png)
![Slide 33](http://nedbatchelder.com/text/devdays/devdays_033.png)
Here’s the completed Nango code:
import re
class Nango1(object):
def __init__(self, text):
# Convert {{foo}} into %(foo)s
text = re.sub(r"{{(.+?)}}", r"%(\1)s", text)
self.text = text
def render(self, data):
return self.text % NangoContext(data)
class NangoContext(object):
def __init__(self, data):
self.data = data
def __getitem__(self, key):
if "." in key:
dots = key.split('.')
value = self[dots[0]]
for dot in dots[1:]:
try:
value = getattr(value, dot)
except AttributeError:
value = value[dot]
if callable(value):
value = value()
else:
value = self.data[key]
return value
![Slide 34](http://nedbatchelder.com/text/devdays/devdays_034.png)
![Slide 35](http://nedbatchelder.com/text/devdays/devdays_035.png)
![Slide 36](http://nedbatchelder.com/text/devdays/devdays_036.png)
![Slide 37](http://nedbatchelder.com/text/devdays/devdays_037.png)