SlideShare a Scribd company logo
A Few of My Favorite Things




         Mike Pirnat • AG Interactive • CodeMash 2012
A Few of My Favorite Things




         Mike Pirnat • AG Interactive • CodeMash 2012
A Few of My Favorite (Python) Things
Disclaimers
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
A Few of My Favorite (Python) Things
The Language
_                                             (                   =
                                          255,
                                       lambda
                                V       ,B,c
                             :c    and Y(V*V+B,B, c
                                -1)if(abs(V)<6)else
               (              2+c-4*abs(V)**-0.4)/i
                 ) ;v,       x=1500,1000;C=range(v*x
                  );import struct;P=struct.pack;M,
            j ='<QIIHHHH',open('M.bmp','wb').write
for X in j('BM'+P(M,v*x*3+26,26,12,v,x,1,24))or C:
            i ,Y=_;j(P('BBB',*(lambda T:(T*80+T**9
                  *i-950*T **99,T*70-880*T**18+701*
                 T **9      ,T*i**(1-T**45*2)))(sum(
               [              Y(0,(A%3/3.+X%v+(X/v+
                                A/3/3.-x/2)/1j)*2.5
                             /x    -2.7,i)**2 for 
                                A       in C
                                       [:9]])
                                          /9)
                                        )     )

        http://preshing.com/20110926/high-resolution-mandelbrot-in-obfuscated-python
http://preshing.com/20110926/high-resolution-mandelbrot-in-obfuscated-python
The Interactive Shell

$ python
Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build
2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for
more information.
>>>
Docstrings...
class Frobulator(object):
    """It frobulates things."""

    def __init__(self, doohickey):
        """A Frobulator needs a doohickey."""
        self.doohickey = doohickey

    def frobulate(self):
        """Frobulate ALL the things!"""
        print "Frobulating..."
        doodad = self.doohickey()
        return FrobulatedThing(doodad)


class FrobulatedThing(object):
    """A thing which has been frobulated."""

    def __init__(self, thing):
        """Make a thing into a frobulated thing."""
        self.thing = thing
...and Help
>>> help(Frobulator)

Help on class Frobulator in module frobulator:

class Frobulator(__builtin__.object)
 | It frobulates things.
 |
 | Methods defined here:
 |
 | __init__(self, doohickey)
 |      A Frobulator needs a doohickey.
 |
 | frobulate(self)
 |      Frobulate ALL the things!
 |
 ...
Comprehensions

• List comprehensions
• Set comprehensions
• Dictionary comprehensions
• Generator expressions
List Comprehensions

x = [item for item in series]

x = [do_something(item) for item in series if expression]

things = [Thingy.from_data(x) for x in database_results]

partiers = [x for x in codemashers if x.slides_done()]
List Comprehensions
booze = ['beer', 'wine', 'scotch', 'gin']
soft_drinks = ['water', 'soda', 'juice']

a = [(x, y) for x in booze for y in soft_drinks]

[('beer', 'water'), ('beer', 'soda'), ('beer', 'juice'),
('wine', 'water'), ('wine', 'soda'), ('wine', 'juice'),
('scotch', 'water'), ('scotch', 'soda'), ('scotch',
'juice'), ('gin', 'water'), ('gin', 'soda'), ('gin',
'juice')]
List Comprehensions


b = [x for x in zip(booze, soft_drinks)]

[('beer', 'water'), ('wine', 'soda'), ('scotch', 'juice')]
Set Comprehensions


s = {v for v in 'CODEMASH ROCKS' if v not in 'ABCD'}

set([' ', 'E', 'H', 'K', 'M', 'O', 'S', 'R'])
Dictionary Comprehensions
 d = {key: value for key, value in list_of_tuples}

 d = {
     'Mike': 'Python',
     'Jim': 'Ruby',
     'Brad': 'UX',
     ...
     }

 d1 = {val: key for key, val in d.items()}

 {'Python': 'Mike', 'Ruby': 'Jim', 'UX': 'Brad', ...}
Generators
def f(how_many):
    for number in range(how_many):
        if number**2 > 3:
            yield number * 2

for number in f(5):
    print number

4
6
8
Generator Expressions

gen = (2*x for x in range(5) if x**2 > 3)

for number in gen:
    print number

4
6
8
Properties

class Foo(object):

    def __init__(self, bar=42):
        self.set_bar(bar)

    def get_bar(self):
        return self.bar

    def set_bar(self, bar):
        self.bar = int(bar)
Properties
class Foo(object):

    def __init__(self, bar=42):
        self.bar = bar

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, x):
        self._bar = int(x)
Properties
class Foo(object):

    def __init__(self, bar=42):
        self.bar = bar

    @property
    def bar(self):
        return self._bar

    @bar.setter
    def bar(self, x):
        self._bar = int(x)
Properties

>>> foo = Foo()
>>> foo.bar
42
>>> foo.bar = 'abc'
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 9, in bar
ValueError: invalid literal for int() with base 10:
'abc'
Decorators

• That funny-looking @ thing
• Similar to Java’s annotations
• Replaces a function with a wrapper
• Augment functionality in a reusable way
Decorators
def be_excellent(wrapped):
    def wrapper(*args, **kwargs):
        print "Be excellent to each other..."
        return wrapped(*args, **kwargs)
    return wrapper

@be_excellent
def party_on(who):
    print "...and party on, {0}!".format(who)

>>> party_on('dudes')
Be excellent to each other...
...and party on, dudes!
Context Managers
• That funny “with” thing
• Simplify calling code that needs setup and
  teardown
• Alternative to try/finally structures
• Acquire locks, open and close files, do
  database transactions, etc.
Before Context Managers

frobulator = Frobulator(...)

try:
    frobulator.frobulate()
finally:
    frobulator.cleanup()
After Context Managers


with Frobulator(...) as frobulator:
    frobulator.frobulate()
class Frobulator(object):

    def __init__(self, ...):
        ...

    def __enter__(self):
        print "Preparing to frobulate..."
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        print "Frobulation complete!"

    def frobulate(self):
        print "Frobulating!"
        ...
with Frobulator() as frobulator:
    frobulator.frobulate()


Preparing to frobulate...
Frobulating!
Frobulation complete!
import contextlib

@contextlib.contextmanager
def make_frobulator():
    print "Preparing to frobulate..."
    yield Frobulator()
    print "Frobulation complete!"


with make_frobulator() as frobulator:
    frobulator.frobulate()


Preparing to frobulate...
Frobulating!
Frobulation complete!
The Standard Library
Itertools

• Tools for iterating on sequences
• Inspired by functional languages
• Fast and memory efficient
• Combine to express more complicated
  algorithms
Itertools: chain

from itertools import chain

for x in chain([1, 2, 3], [42, 1138, 2112]):
     print x,


1 2 3 42 1138 2112
Itertools: izip

from itertools import izip

for x in izip([1, 2, 3], [42, 1138, 2112]):
    print x,


(1, 42) (2, 1138) (3, 2112)
Itertools: islice
from itertools import islice, count

for x in islice(count(), 5):
    print x,

for x in islice(count(), 5, 10):
    print x,

for x in islice(count(), 0, 100, 10):
    print x,

0 1 2 3 4
5 6 7 8 9
0 10 20 30 40 50 60 70 80 90
Itertools: islice
from itertools import islice, count

for x in islice(count(), 5):
    print x,

for x in islice(count(), 5, 10):
    print x,

for x in islice(count(), 0, 100, 10):
    print x,

0 1 2 3 4
5 6 7 8 9
0 10 20 30 40 50 60 70 80 90
Itertools: imap


from itertools import imap

for thingy in imap(Thingy.from_data, database_results):
    ...
Itertools: cycle
from itertools import cycle

for x in cycle(['wake up', 'meet Ned', 'romance Rita']):
    print x

wake up
meet Ned
romance Rita
wake up
meet Ned
romance Rita
wake up
meet Ned
...
Itertools: repeat

from itertools import repeat

for x in repeat("stop hitting yourself", 5):
    print x

stop   hitting   yourself
stop   hitting   yourself
stop   hitting   yourself
stop   hitting   yourself
stop   hitting   yourself
Functools

• Tools for manipulating functions
• Partial
• Wraps a callable with default arguments
• Alternative to lambdas and closures
Functools: Partial
from functools import partial

def f(a, b=2):
    print a, b

f1 = partial(f, 'fixed_a')
f2 = partial(f, b='fixed_b')

>>> f1(b=1138)
fixed_a 1138

>>> f2(1138)
1138 fixed_b
Functools: Partial
def category_is(category, item):
    categories = [x.lower() for x in item.categories]
    if category.lower() in categories:
        return True
    return False

is_python = partial(category_is, 'python')
is_cat_pictures = partial(category_is, 'catpix')

...

python_posts = [item for item in blog_posts if is_python(item)]

cat_posts = [item for item in blog_posts if is_cat_pictures(item)]
Collections
• Beyond the basic list, dict, tuple, and set...
• Counter
• Defaultdict
• OrderedDict
• Namedtuple
• ...and more
Counter
counter = {}
for char in "Hello there, CodeMash!":
    if char not in counter:
        counter[char] = 1
    else:
        counter[char] += 1

print counter

{'a': 1, ' ': 2, 'C': 1, 'e': 4, 'd': 1, 'H': 1, 'M': 1,
'l': 2, 'o': 2, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1,
'h': 2}
Counter
counter = {}
for char in "Hello there, CodeMash!":
    if char not in counter:
        counter[char] = 1
    else:
        counter[char] += 1

print counter

{'a': 1, ' ': 2, 'C': 1, 'e': 4, 'd': 1, 'H': 1, 'M': 1,
'l': 2, 'o': 2, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1,
'h': 2}
Counter

from collections import Counter
counter = Counter("Hello there, CodeMash!")
print counter

Counter({'e': 4, ' ': 2, 'l': 2, 'o': 2, 'h': 2, 'a': 1,
'C': 1, 'd': 1, 'H': 1, 'M': 1, ',': 1, 's': 1, 'r': 1,
'!': 1, 't': 1})
Counter

from collections import Counter
counter = Counter("Hello there, CodeMash!")
print counter

Counter({'e': 4, ' ': 2, 'l': 2, 'o': 2, 'h': 2, 'a': 1,
'C': 1, 'd': 1, 'H': 1, 'M': 1, ',': 1, 's': 1, 'r': 1,
'!': 1, 't': 1})
Namedtuple
import math

def distance(a, b):
    return math.sqrt(
        (a[0] - b[0])**2 +
        (a[1] - b[1])**2 +
        (a[2] - b[2])**2
    )

a = (1, 2, 3)
b = (-1, -2, 42)
print distance(a, b)

39.25557285278104
Namedtuple
from collections import namedtuple
Point = namedtuple('Point', 'x y z')

def distance(a, b):
    return math.sqrt(
        (a.x - b.x)**2 +
        (a.y - b.y)**2 +
        (a.z - b.z)**2
    )

a = Point(x=1, y=2, z=3)
b = Point(-1, -2, 42)
print distance(a, b)

39.25557285278104
Difflib
s1 = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus dui nunc, faucibus id ullamcorper eget, tempus
vitae nisl. Donec quis semper risus. Curabitur sit amet
tellus eget metus accumsan porta nec nec lorem. Ut vitae
sem nisl. Praesent pulvinar feugiat nibh fringilla
semper. Nullam cursus tempor lorem ut egestas. Nullam
suscipit gravida turpis ac porttitor. Curabitur eleifend
augue at risus commodo pretium. Aliquam eget magna
risus, ut lobortis metus. Cum sociis natoque penatibus
et magnis dis parturient montes, nascetur ridiculus mus.
Etiam non magna sit amet nulla porttitor molestie sit
amet vel sem. Vestibulum sit amet nisl a velit
adipiscing porta id non urna. Duis ullamcorper dictum
ipsum sit amet congue.
"""
Difflib
s2 = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Phasellus dui nunc, faucibus id ullamcorper eget, tempus
vitae nisl. Donec quis semper risus. Curabitur sit amet
tellus eget metus accumsan porta nec nec lorem. Ut vitae
sem nisl. Praesent pulvinar feugiat nibh fringilla
semper. Nullam cursus tempor lorem ut egestas. Nullam
suscipit gravida turpis ac porttitor. Curabitur eleifend
augue at risus commodo pretium. Aliquam eget magna
risus, ut lobortis montes. Cum sociis natoque penatibus
et magnis dis parturient metus, nascetur ridiculus mus.
Etiam non magna sit amet nulla porttitor molestie sit
amet vel sem. Vestibulum sit amet nisl a velit
adipiscing porta id non urna. Duis ullamcorper dictum
ipsum sit amet congue.
"""
Difflib

import difflib

differ = difflib.Differ()
diff = differ.compare(s1.splitlines(), s2.splitlines())
print 'n'.join(diff)
Difflib
  Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  Phasellus dui nunc, faucibus id ullamcorper eget, tempus
  vitae nisl. Donec quis semper risus. Curabitur sit amet
  tellus eget metus accumsan porta nec nec lorem. Ut vitae
  sem nisl. Praesent pulvinar feugiat nibh fringilla
  semper. Nullam cursus tempor lorem ut egestas. Nullam
  suscipit gravida turpis ac porttitor. Curabitur eleifend
  augue at risus commodo pretium. Aliquam eget magna
- risus, ut lobortis metus. Cum sociis natoque penatibus
?                      --

+ risus, ut lobortis montes. Cum sociis natoque penatibus
?                     +++

- et magnis dis parturient montes, nascetur ridiculus mus.
?                           ^^ ^

+ et magnis dis parturient metus, nascetur ridiculus mus.
?                           ^ ^

  Etiam non magna sit amet nulla porttitor molestie sit
  amet vel sem. Vestibulum sit amet nisl a velit
  adipiscing porta id non urna. Duis ullamcorper dictum
  ipsum sit amet congue.
Difflib


diff = difflib.unified_diff(
        s1.splitlines(), s2.splitlines(), lineterm='')
print 'n'.join(diff)
Difflib

---
+++
@@ -7,8 +7,8 @@
 semper. Nullam cursus tempor lorem ut egestas. Nullam
 suscipit gravida turpis ac porttitor. Curabitur eleifend
 augue at risus commodo pretium. Aliquam eget magna
-risus, ut lobortis metus. Cum sociis natoque penatibus
-et magnis dis parturient montes, nascetur ridiculus mus.
+risus, ut lobortis montes. Cum sociis natoque penatibus
+et magnis dis parturient metus, nascetur ridiculus mus.
 Etiam non magna sit amet nulla porttitor molestie sit
 amet vel sem. Vestibulum sit amet nisl a velit
 adipiscing porta id non urna. Duis ullamcorper dictum
Ast

• Use Python to process abstract syntax trees
  of Python grammar
• Helps introspect about what the current
  grammar looks like
• Helps write secure code
Ast

# Danger:
foo = eval(bar)

# Safe:
foo = ast.literal_eval(bar)
Multiprocessing
• Like threading, but with subprocesses
• Local and remote concurrency
• Spawn processes or entire pools
• Communicate via queues or pipes
• Shared state via shared memory or
  manager/server process
import os
from multiprocessing import Process

def info(title):
    print title
    print 'parent process:', os.getppid()
    print 'process id:', os.getpid()

def f(name):
    info('function f')
    print 'hello', name

if __name__ == '__main__':
    info('main')
    p = Process(target=f, args=('world',))
    p.start()
    p.join()
$ python process.py
main
parent process: 18647
process id: 31317
----------
function f
parent process: 31317
process id: 31318
----------
hello world
import os
from multiprocessing import Pool

def g(x):
    info('function g('+str(x)+')')
    return x * x

if __name__ == '__main__':
    info('main')
    pool = Pool(2)
    print pool.map(g, range(100))
$ python process.py     parent process: 31369
main                    parent process: 31369
module name: __main__   process id: 31370
parent process: 18647   process id: 31371
process id: 31369       ----------
----------              ----------
function g(0)           function g(4)
module name: __main__   module name: __main__
parent process: 31369   parent process: 31369
process id: 31370       function g(14)
----------              process id: 31370
function g(1)           module name: __main__
module name: __main__   ----------
parent process: 31369   parent process: 31369
process id: 31370       function g(5)
----------              process id: 31371
function g(13)          module name: __main__
function g(2)
module name: __main__   ...
parent process: 31369
process id: 31370       [0, 1, 4, 9, 16, 25, ..., 8836,
----------              9025, 9216, 9409, 9604, 9801]
module name: __main__
function g(3)
module name: __main__
Third Party Packages
Third Party Packages

• Most available on PyPI--http://pypi.python.org
• pip install packagename
• easy_install packagename
Virtualenv

• Makes an isolated Python environment
• Don’t pollute your global site-packages
• Insulates Python projects from one another
• Don't have to be root
Virtualenv
$ virtualenv directory

$ virtualenv --python=/path/to/specific/python directory

$ cd directory
$ . bin/activate

$ easy_install whatever
$ pip install whatever

...do stuff...

$ deactivate
Datetime and Dateutil
• Python’s datetime provides date, time,
  datetime, and timedelta objects
• Dateutil provides powerful extensions
• Parsing
• Olson-driven timezones
• Recurrence
Parsing

>>> from dateutil.parser import parse

>>> parse('01/01/2012')
datetime.datetime(2012, 1, 1, 0, 0)

>>> parse('2012-01-01')
datetime.datetime(2012, 1, 1, 0, 0)
Timezones
>>> from dateutil import zoneinfo

>>> zone = zoneinfo.gettz('US/Eastern')
>>> zone
tzfile('America/New_York')
>>> zone2 = zoneinfo.gettz('US/Hawaii')

>>> dt = datetime.now(zone)
>>> dt
datetime.datetime(2012, 1, 13, 13, 46, 54, 997825,
tzinfo=tzfile('America/New_York'))

>>> dt.astimezone(zone2)
datetime.datetime(2012, 1, 13, 8, 46, 54, 997825,
tzinfo=tzfile('Pacific/Honolulu'))
Recurrence
>>> from dateutil.rrule import rrule, YEARLY, MONTHLY,
WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, BY_EASTER

>>> rr = rrule(YEARLY, dtstart=datetime(1948, 2, 24))

>>> rr.after(datetime(2012, 1, 1))
datetime(2012, 2, 24, 0, 0)

>>> rr.between(datetime(2010, 1, 1),
        datetime(2012, 1, 1))
[datetime(2010, 2, 24, 0, 0),
        datetime(2011, 2, 24, 0, 0)]
howoldismykid.com
def periods_between(freq, start_date, end_date):

    # dateutil.rrule falls down for monthly recurrences where the start
    # date's day is greater than the number of days in a subsequent month
    # in the range; ie, when start date is 10/31/2010, and end date is
    # 3/13/2011, rrule's between will only produce 2 instances, 12/31 and
    # 1/31, rather than 4.
    if freq == MONTHLY and start_date.day > 28:
        start_date = datetime.datetime(start_date.year, start_date.month,
                28, start_date.hour, start_date.minute, start_date.second)

    # Same problem but for "Pirates of Penzance" leap day birthdays...
    elif freq == YEARLY and is_leap_day(start_date):
        start_date = datetime.datetime(start_date.year, start_date.month,
                28, start_date.hour, start_date.minute, start_date.second)

    rr = rrule(freq, dtstart=start_date)
    periods = len(rr.between(start_date, end_date))
    return periods
howoldismykid.com
>>> start_date = datetime(2007, 9, 10)
>>> end_date = datetime(2012, 1, 13)

>>> periods_between(YEARLY, start_date, end_date)
4

>>> periods_between(MONTHLY, start_date, end_date)
52

>>> periods_between(WEEKLY, start_date, end_date)
226

>>> periods_between(DAILY, start_date, end_date)
1585
Nose

• Find, run, and report results of test suites
• Low-friction setup
• Extendable with plugins (more later)
• http://readthedocs.org/docs/nose/en/latest/
Nose

# test_foo.py

def test_a_thing():
    assert False

def test_another_thing():
    assert True
Nose
$ nosetests tests/test_foo.py
F.
======================================================================
FAIL: test_foo.test_a_thing
----------------------------------------------------------------------
Traceback (most recent call last):
   File "/Users/mpirnat/Code/frobulator/lib/python2.7/site-packages/
nose-1.1.2-py2.7.egg/nose/case.py", line 197, in runTest
     self.test(*self.arg)
   File "/Users/mpirnat/Code/frobulator/src/frobulator/tests/test_foo.py",
line 2, in test_a_thing
     assert False
AssertionError

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)
Nose
class TestWhenFrobulating(object):

    def setup(self):
        self.frobulator = Frobulator()
        self.frobulator.frobulate()

    def test_that_it_frobulated(self):
        assert self.frobulator.has_frobulated

    def teardown(self):
        self.frobulator.cleanup()
Nose

$ nosetests
.
--------------------------------------------------------
Ran 1 test in 0.005s

OK
Nose: Useful Flags

• --processes=number
• -x
• --pdb
• --pdb-failures
• --failed
Nose Plugins
• Add custom behavior to your test run
• Get coverage statistics (coverage)
• Measure cleanliness with PEP-8 (tissue)
• Emit human-readable spec-style results
  (pinocchio)
• Or write your own...
class TestGeneratesLotsOfFailures(object):

    def test_generates_failures(self):

        def _make_a_test(i):
            # start with some wins
            if i < 7:
                assert True

            # but then it hits the fan...
            elif i < 30:
                assert False

            # then be a little random
            elif i % 3 == 0:
                assert False
            else:
                assert True

        for i in range(50):
            yield _make_a_test, i
$ nosetests test_epic_fail.py

.......FFFFFFFFFFFFFFFFFFFFFFFF..F..F..F..F..F..F.
[lots of test failure output; use your imagination...]
--------------------------------------------------------
Ran 50 tests in 0.010s

FAILED (errors=30)
A Few of My Favorite (Python) Things
import os
from nose.plugins import Plugin

class F7U12(Plugin):

    name = 'f7u12'
    enabled = True

    def options(self, parser, env=os.environ):
        super(F7U12, self).options(parser, env=env)

    def configure(self, options, config):
        super(F7U12, self).configure(options, config)
        self.config = config
        if not self.enabled:
            return
def setOutputStream(self, stream):
    self.stream = stream
    return self.stream

def begin(self):
    self.failure_count = 0

def handleFailure(self, test, err):
    self.failure_count += 1

    if self.failure_count < 8:
        self.stream.write('F')
    else:
        self.stream.write('U')
    return True
$ nosetests --with-f7u12 test_epic_fail.py

.......FFFFFFFFUUUUUUUUUUUUUUUU..U..U..U..U..U..U.
[lots of test failure output; use your imagination...]
--------------------------------------------------------
Ran 50 tests in 0.010s

FAILED (errors=30)
Mock
• Mock object framework
• Avoid writing custom stubs
• Uses “Action/Assert” model (not “Record/
  Replay”)
• Can also patch out module and class
  attributes in the scope of a test
• http://www.voidspace.org.uk/python/mock/
Mock

from mock import Mock

foo = Mock()
foo.bar()
foo.bar.baz(42)
foo.bar.baz.return_value = "whatever"

assert foo.bar.called
foo.bar.baz.assert_called_with(42)
Mock

class TestWhenFrobulating(object):

    def setup(self):
        self.doohickey = Mock()
        self.frobulator = Frobulator(self.doohickey)
        self.frobulator.frobulate()

    def test_it_uses_the_doohickey(self):
        assert self.doohickey.called
Mock
from mock import patch

class TestWhenFrobulating(object):

    @patch('frobulator.DingleHopper')
    def setup(self, dingle_hopper_class):
        self.dingle_hopper = Mock()
        dingle_hopper_class.return_value = 
                self.dingle_hopper
        self.frobulator = Frobulator()
        self.frobulator.frobulate()

    def test_it_uses_a_dingle_hopper(self):
        assert self.dingle_hopper.called
Coverage

• Measure coverage of your codebase during
  program execution
• Integrates with several test runners to
  measure test coverage
• http://nedbatchelder.com/code/coverage/
#!/usr/bin/env python

class Frobulator(object):
    """It frobulates things."""

    def __init__(self, doohickey):
        """A Frobulator needs a doohickey."""
        self.doohickey = doohickey

    def frobulate(self):
        """Frobulate ALL the things!"""
        print "Frobulating..."
        doodad = self.doohickey()
        return FrobulatedThing(doodad)


class FrobulatedThing(object):
    """A thing which has been frobulated."""

    def __init__(self, thing):
        """Make a thing into a frobulated thing."""
        self.thing = thing


if __name__ == '__main__':
    x = FrobulatedThing(42)
#!/usr/bin/env python

class Frobulator(object):
    """It frobulates things."""

    def __init__(self, doohickey):
        """A Frobulator needs a doohickey."""
        self.doohickey = doohickey

    def frobulate(self):
        """Frobulate ALL the things!"""
        print "Frobulating..."
        doodad = self.doohickey()
        return FrobulatedThing(doodad)


class FrobulatedThing(object):
    """A thing which has been frobulated."""

    def __init__(self, thing):
        """Make a thing into a frobulated thing."""
        self.thing = thing


if __name__ == '__main__':
    x = FrobulatedThing(42)
$ coverage run frobulator.py

$ coverage report -m
Name         Stmts   Miss Cover    Missing
------------------------------------------
frobulator      12      4    67%   8, 12-14
from mock import Mock, patch
from frobulator import Frobulator, FrobulatedThing


class TestWhenFrobulating(object):

    def setup(self):
        self.doohickey = Mock()
        self.doohickey.return_value = 42

        self.frobulator = Frobulator(self.doohickey)
        self.result = self.frobulator.frobulate()

    def test_it_uses_a_doohickey(self):
        assert self.doohickey.called

    def test_it_returns_a_frobulated_thing(self):
        assert isinstance(self.result, FrobulatedThing)
$ nosetests --with-coverage --cover-package frobulator
..
Name         Stmts    Miss Cover   Missing
------------------------------------------
frobulator      12       1   92%   26
------------------------------------------
Ran 2 tests in 0.008s

OK
Useful Flags

• --cover-erase
• --cover-inclusive
• --cover-tests
Lettuce

• Like Cucumber
• BDD test framework
• Natural language augmented by code
• Big wins pairing Devs + QA + Biz
• http://lettuce.it/
Lettuce Vocabulary

• Features
• Scenarios
• Steps
• World
• Terrain
Feature: The website has a homepage
    In order to demo Lettuce
    As a presenter
    I want to test the homepage of a website

    Scenario: Verify the site is up
        Given I access the url "http://localhost:8000/"
        Then I get a status "200"
from lettuce import step, world
from nose.tools import assert_equals
import requests


@step(r'I access the url "(.*)"')
def access_url(step, url):
    world.response = requests.get(url)


@step(r'I get a status "(.*)"')
def get_status(step, expected_status):
    expected_status = int(expected_status)
    assert_equals(world.response.status_code,
            expected_status)
Snake-Guice

• Framework for Dependency Injection
• Reduce coupling!
• Improve testability!
• http://code.google.com/p/snake-guice/
Snake-Guice
• Bind identifiers to things you want to inject
• Decorate code with injection hints
• Use injector to get instance with all
  dependencies resolved and injected
• Construct with mocks in tests, minimize the
  need for patching
Define the Identifier


class IFrobulator(object):
    pass
Decorate Your Code

from snakeguice import inject


class WankelRotator(object):

    @inject(frobulator=IFrobulator)
    def __init__(self, frobulator):
        self.frobulator = frobulator
Decorate Your Code

from snakeguice import inject


class WankelRotator(object):

    @inject(frobulator=IFrobulator)
    def __init__(self, frobulator):
        self.frobulator = frobulator
Configure Bindings

from frobulator import Frobulator


class BindingModule(object):

    def configure(self, binder):
        binder.bind(IFrobulator, to=Frobulator)
Get an Instance

from snakeguice import Injector
import WankelRotator

injector = Injector(BindingModule())
rotator = injector.get_instance(WankelRotator)
Requests

• A human-friendly alternative to urllib2
• Maturing rapidly
• http://python-requests.org/
Using Requests

import requests

# Authentication!
r = requests.get('https://api.github.com',
        auth=('user', 'pass'))

print r.status_code
print r.headers['content-type']
Using Requests

# Posting name-value pair form data
post_data = {'foo': 'bar', 'baz': 'quux', ...}
r = requests.post(url, data=post_data)

# Posting a glob of JSON
r = requests.post(url, data=json.dumps(post_data))

# Multipart file attachment
files = {'my_file.xls': open('my_file.xls', 'rb')}
r = requests.post(url, files=files)
Using Requests

# Custom headers!
headers = {'X-foo': 'bar'}
r = requests.get(url, headers=headers)

# Cookies!
cookies = {'a_cookie': 'is delicious'}
r = requests.get(url, cookies=cookies)
Pylons
• http://docs.pylonsproject.org/en/latest/docs/
  pylons.html
• MVCish web framework
• Glues together several component projects
• Can use your preferred components
• Somewhat dead (evolved into Pyramid)
Pylons
• Request/response: webob
• URL dispatch: routes
• Input validation: formencode
• Persistence/ORM: sqlalchemy
• Session: beaker
• Templates: mako
from routes import Mapper


def make_map(config):
    """Create, configure and return the routes Mapper"""
    map = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'])
    ...

    map.connect('/', controller='main', action='index')
    map.connect('/contact', controller='contact', action='index',
            conditions={'method':'GET'})
    map.connect('/contact', controller='contact', action='send',
            conditions={'method':'POST'})

    return map
from howoldismykid.lib.base import BaseController, 
        render


class MainController(BaseController):

    def index(self):
        # Return a rendered template
        return render('/main.mako')
from formencode import Schema, validators

class ContactForm(Schema):
    email = validators.Email(not_empty=True)
    subject = validators.String(not_empty=True)
    message = validators.String(not_empty=True)
from pylons.decorators import validate
from howoldismykid.lib.base import BaseController, render
from howoldismykid.model.forms import ContactForm

class ContactController(BaseController):

    def __init__(self, *args, **kwargs):
        BaseController.__init__(self, *args, **kwargs)
        self.emailer = Emailer(SMTP, USER, PW, FAKE_EMAIL)

    def index(self):
        # Return a rendered template
        return render('/contact.mako')

    @validate(schema=ContactForm(), form="index", prefix_error=False)
    def send(self):
        validated = self.form_result
        self.emailer.send_mail(validated['email'], EMAIL,
                validated['subject'], validated['message'])
        return render('/contact_done.mako')
<!DOCTYPE HTML>
<html>
    <head>
        ${self.head_tags()}
        ...
    </head>
    <body>
        <div id="header">...</div>
        <div id="content">
            ${self.body()}
        </div>

        <div id="footer">...</div>

        <%include file="google_analytics.mako"/>
        ${self.foot_tags()}

    </body>
</html>
<%inherit file="/base.mako" />

<%def name="head_tags()">
<title>How Old Is My Kid?</title>
</%def>

<h2>Contact Us</h2>

<p>Suggest a new feature, let us know how we're doing, or just say hi.</p>

<form method="POST" action="/contact" id="contact-form">
    <p><label for="email">Email:</label> <input type="text" name="email"
id="email" /></p>
    <p><label for="subject">Subject:</label> <input type="text"
name="subject" id="subject" /></p>
    <p><label for="message">Message:</label><br />
<textarea name="message" id="message"></textarea></p>
    <p><input type="submit" value="Submit" /></p>
</form>

<%def name="foot_tags()">
<script type="text/javascript">
$(document).ready(function() {
    $("button, input:submit").button();
});
</script>
</%def>
Django
• https://www.djangoproject.com/
• Full stack/harder to replace components
• Lots of reusable apps
• Admin interface
• Lots of deployment options (Google)
• Not dead
from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('',
    url(r'^/$', 'howoldismykid.views.main',
            name='main'),
    url(r'^/contact/$', 'howoldismykid.views.contact',
            name='contact'),
)
from django.shortcuts import render

def main(request):
    return render(request, 'main.html')
from django import forms


class ContactForm(forms.Form):

    email = forms.EmailField(label='Email Address')
    subject = forms.CharField(label='Subject')
    message = forms.CharField(label='Message',
            widget=forms.Textarea)
from contact.forms import ContactForm
from django.shortcuts import render

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            emailer = 
                    Emailer(SMTP, USER, PW, FAKE_EMAIL)
            emailer.send_mail(
                    form.cleaned_data['email'], EMAIL,
                    form.cleaned_data['subject'],
                    form.cleaned_data['message'])
            return render(request, 'contact_done.html')
    else:
        form = ContactForm()

    return render(request, 'contact.html',
        {'form': form })
<!DOCTYPE HTML>
<html>
    <head>
        {% block head_tags %}...{% endblock %}
        ...
    </head>
    <body>
        <div id="header">...</header>
        <div id="content">
            {% block content %}It goes here.{% endblock %}
        </div>

        <div id="footer">...</div>

        {% include "google_analytics.html" %}
        {% block foot_tags %}{% endblock %}

    </body>
</html>
{% extends 'base.html' %}

{% block head_tags %}
<title>How Old Is My Kid?</title>
{% endblock %}

{% block content %}
<h2>Contact Us</h2>

<p>Suggest a new feature, let us know how we're doing, or just say hi.</p>

<form method="POST" action="/contact" id="contact-form">
    {% csrf_token %}
    {{ form.as_p }}
    <p><input type="submit" value="Submit" /></p>
</form>
{% endblock %}

{% block foot_tags %}
<script type="text/javascript">
$(document).ready(function() {
    $("button, input:submit").button();
});
</script>
{% endblock %}
The Culture
Planet Python

• http://planet.python.org/
• Aggregate feed of Python blogs
• Great way to follow what's going on
• Minimize newsgroup/mailing list burdens
• Easy to be included
The Python Ecosystem

• http://mirnazim.org/writings/python-
  ecosystem-introduction/
• Great introduction to the Python ecosystem
• Everything you need to get up and running
The Hitchhiker’s Guide

• http://docs.python-guide.org/
• Opinionated advice about using Python
• Basics
• Scenario-specific details and
  recommendations
PyMotW
• Explored a different standard library module
  every week
• Examples, examples, examples
• http://www.doughellmann.com/PyMOTW/
• The Python Standard Library by Example
  http://www.doughellmann.com/books/byexample/
Podcasts
• http://www.radiofreepython.com/
• http://frompythonimportpodcast.com/
• http://djangodose.com/
• http://advocacy.python.org/podcasts/
• http://www.awaretek.com/python/
• Start your own! Be the change you want...
PyOhio

• Free as in $0.00
• Columbus, Ohio
• Last weekend in July
• http://pyohio.org
PyCon
• Great people
• Great vibe
• All volunteer–personal ownership
• Video! http://pycon.blip.tv/
• 2012 & 2013: Santa Clara
• 2014 & 2015: Montreal
TiP BoF

• Testing in Python Birds of a Feather
• Lightning Talks
• Heckling...
...and goats
The Zen


• Guiding principles
• Sage advice
• >>>   import this
The Zen
• Beautiful is better than ugly.   • Readability counts.
• Explicit is better than          • Special cases aren't special
   implicit.                          enough to break the rules.

• Simple is better than            • Although practicality beats
   complex.                           purity.

• Complex is better than           • Errors should never pass
   complicated.                       silently.

• Flat is better than nested.      • Unless explicitly silenced.
• Sparse is better than dense.
The Zen
• In the face of ambiguity,    • Although never is often
   refuse the temptation to       better than right now.
   guess.
                               • If the implementation is
• There should be one–            hard to explain, it's a bad
   and preferably only one–       idea.
   obvious way to do it.
                               • If the implementation is
• Although that way may not       easy to explain, it may be a
   be obvious at first unless      good idea.
   you're Dutch.
                               • Namespaces are one
• Now is better than never.       honking great idea -- let's
                                  do more of those!
What About You?
Fin

• Twitter: @mpirnat
• Blog: http://mike.pirnat.com
• Win a special prize–name all the movies
• Thanks for coming!
Ad

More Related Content

What's hot (20)

PHP 7 – What changed internally?
PHP 7 – What changed internally?PHP 7 – What changed internally?
PHP 7 – What changed internally?
Nikita Popov
 
Haskell in the Real World
Haskell in the Real WorldHaskell in the Real World
Haskell in the Real World
osfameron
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
Fwdays
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
kwatch
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
Nikita Popov
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010
Qiangning Hong
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
James Titcumb
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)
RORLAB
 
Groovy presentation
Groovy presentationGroovy presentation
Groovy presentation
Manav Prasad
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
Rémy-Christophe Schermesser
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Charles Nutter
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
Brendan Eich
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
Fwdays
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
Nikita Popov
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to Pig
Chris Wilkes
 
Opaque Pointers Are Coming
Opaque Pointers Are ComingOpaque Pointers Are Coming
Opaque Pointers Are Coming
Nikita Popov
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
Kent Ohashi
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
takeoutweight
 
PHP 7 – What changed internally?
PHP 7 – What changed internally?PHP 7 – What changed internally?
PHP 7 – What changed internally?
Nikita Popov
 
Haskell in the Real World
Haskell in the Real WorldHaskell in the Real World
Haskell in the Real World
osfameron
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
Fwdays
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
kwatch
 
PHP Performance Trivia
PHP Performance TriviaPHP Performance Trivia
PHP Performance Trivia
Nikita Popov
 
Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010Python于Web 2.0网站的应用 - QCon Beijing 2010
Python于Web 2.0网站的应用 - QCon Beijing 2010
Qiangning Hong
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
James Titcumb
 
Active Support Core Extensions (1)
Active Support Core Extensions (1)Active Support Core Extensions (1)
Active Support Core Extensions (1)
RORLAB
 
Groovy presentation
Groovy presentationGroovy presentation
Groovy presentation
Manav Prasad
 
Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?Typed Properties and more: What's coming in PHP 7.4?
Typed Properties and more: What's coming in PHP 7.4?
Nikita Popov
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
Jeff Carouth
 
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Charles Nutter
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
Brendan Eich
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
Fwdays
 
What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
Nikita Popov
 
Pig Introduction to Pig
Pig Introduction to PigPig Introduction to Pig
Pig Introduction to Pig
Chris Wilkes
 
Opaque Pointers Are Coming
Opaque Pointers Are ComingOpaque Pointers Are Coming
Opaque Pointers Are Coming
Nikita Popov
 
Interceptors: Into the Core of Pedestal
Interceptors: Into the Core of PedestalInterceptors: Into the Core of Pedestal
Interceptors: Into the Core of Pedestal
Kent Ohashi
 
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
Haste (Same Language, Multiple Platforms) and Tagless Final Style (Same Synta...
takeoutweight
 

Viewers also liked (20)

Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Michael Pirnat
 
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
James Titcumb
 
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Tom Lee
 
A Few of My Favorite Things
A Few of My Favorite ThingsA Few of My Favorite Things
A Few of My Favorite Things
stumpteacher
 
Jack's Favorite Things
Jack's Favorite ThingsJack's Favorite Things
Jack's Favorite Things
SimonRoyals
 
My favorite things
My favorite thingsMy favorite things
My favorite things
Allyson Haney
 
Favorite things sample
Favorite things sampleFavorite things sample
Favorite things sample
hillaryalex
 
Kristina’s favorite things
Kristina’s favorite thingsKristina’s favorite things
Kristina’s favorite things
Greg Miller
 
Tina’s Favorite Things
Tina’s Favorite ThingsTina’s Favorite Things
Tina’s Favorite Things
Tina Merritt
 
Clothes
ClothesClothes
Clothes
Kenji Saietto
 
Clothes
ClothesClothes
Clothes
Kenji Saietto
 
My favourite thing
My favourite thingMy favourite thing
My favourite thing
lffl
 
Game favorite clothes
Game favorite clothesGame favorite clothes
Game favorite clothes
Ljubica Ruzinska
 
Aula 2
Aula 2Aula 2
Aula 2
Bruna Dalmagro
 
Clothes
ClothesClothes
Clothes
I.E.N° 10187 "El Virrey"
 
Sam's Favorite Things
Sam's Favorite ThingsSam's Favorite Things
Sam's Favorite Things
SimonRoyals
 
Declarative Syntax Definition - Grammars and Trees
Declarative Syntax Definition - Grammars and TreesDeclarative Syntax Definition - Grammars and Trees
Declarative Syntax Definition - Grammars and Trees
Guido Wachsmuth
 
Emmy’s favorite things
Emmy’s favorite thingsEmmy’s favorite things
Emmy’s favorite things
guest8bf0bb
 
My favorite things
My favorite thingsMy favorite things
My favorite things
CaleighFerree
 
Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Shiny, Let’s Be Bad Guys: Exploiting and Mitigating the Top 10 Web App Vulner...
Michael Pirnat
 
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
Climbing the Abstract Syntax Tree (Bulgaria PHP 2016)
James Titcumb
 
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Hugging Abstract Syntax Trees: A Pythonic Love Story (OSDC 2010)
Tom Lee
 
A Few of My Favorite Things
A Few of My Favorite ThingsA Few of My Favorite Things
A Few of My Favorite Things
stumpteacher
 
Jack's Favorite Things
Jack's Favorite ThingsJack's Favorite Things
Jack's Favorite Things
SimonRoyals
 
Favorite things sample
Favorite things sampleFavorite things sample
Favorite things sample
hillaryalex
 
Kristina’s favorite things
Kristina’s favorite thingsKristina’s favorite things
Kristina’s favorite things
Greg Miller
 
Tina’s Favorite Things
Tina’s Favorite ThingsTina’s Favorite Things
Tina’s Favorite Things
Tina Merritt
 
My favourite thing
My favourite thingMy favourite thing
My favourite thing
lffl
 
Sam's Favorite Things
Sam's Favorite ThingsSam's Favorite Things
Sam's Favorite Things
SimonRoyals
 
Declarative Syntax Definition - Grammars and Trees
Declarative Syntax Definition - Grammars and TreesDeclarative Syntax Definition - Grammars and Trees
Declarative Syntax Definition - Grammars and Trees
Guido Wachsmuth
 
Emmy’s favorite things
Emmy’s favorite thingsEmmy’s favorite things
Emmy’s favorite things
guest8bf0bb
 
Ad

Similar to A Few of My Favorite (Python) Things (20)

Stupid Awesome Python Tricks
Stupid Awesome Python TricksStupid Awesome Python Tricks
Stupid Awesome Python Tricks
Bryan Helmig
 
Python-GTK
Python-GTKPython-GTK
Python-GTK
Yuren Ju
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Python Puzzlers
Python PuzzlersPython Puzzlers
Python Puzzlers
Tendayi Mawushe
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonByterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
akaptur
 
Intro to Python
Intro to PythonIntro to Python
Intro to Python
OSU Open Source Lab
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
Kaz Yoshikawa
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
Eduard Tomàs
 
python beginner talk slide
python beginner talk slidepython beginner talk slide
python beginner talk slide
jonycse
 
An overview of Python 2.7
An overview of Python 2.7An overview of Python 2.7
An overview of Python 2.7
decoupled
 
A tour of Python
A tour of PythonA tour of Python
A tour of Python
Aleksandar Veselinovic
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
Muthu Vinayagam
 
Python GTK (Hacking Camp)
Python GTK (Hacking Camp)Python GTK (Hacking Camp)
Python GTK (Hacking Camp)
Yuren Ju
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
UC San Diego
 
Python crush course
Python crush coursePython crush course
Python crush course
Mohammed El Rafie Tarabay
 
Thinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in PythonThinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in Python
Anoop Thomas Mathew
 
Python 1
Python 1Python 1
Python 1
Ramin Najjarbashi
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby Hackers
Eleanor McHugh
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
David Muñoz Díaz
 
The Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in PythonThe Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in Python
OSCON Byrum
 
Stupid Awesome Python Tricks
Stupid Awesome Python TricksStupid Awesome Python Tricks
Stupid Awesome Python Tricks
Bryan Helmig
 
Python-GTK
Python-GTKPython-GTK
Python-GTK
Yuren Ju
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPythonByterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
Byterun, a Python bytecode interpreter - Allison Kaptur at NYCPython
akaptur
 
Idioms in swift 2016 05c
Idioms in swift 2016 05cIdioms in swift 2016 05c
Idioms in swift 2016 05c
Kaz Yoshikawa
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
Eduard Tomàs
 
python beginner talk slide
python beginner talk slidepython beginner talk slide
python beginner talk slide
jonycse
 
An overview of Python 2.7
An overview of Python 2.7An overview of Python 2.7
An overview of Python 2.7
decoupled
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
Muthu Vinayagam
 
Python GTK (Hacking Camp)
Python GTK (Hacking Camp)Python GTK (Hacking Camp)
Python GTK (Hacking Camp)
Yuren Ju
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
UC San Diego
 
Thinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in PythonThinking in Functions: Functional Programming in Python
Thinking in Functions: Functional Programming in Python
Anoop Thomas Mathew
 
Google Go For Ruby Hackers
Google Go For Ruby HackersGoogle Go For Ruby Hackers
Google Go For Ruby Hackers
Eleanor McHugh
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
David Muñoz Díaz
 
The Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in PythonThe Vanishing Pattern: from iterators to generators in Python
The Vanishing Pattern: from iterators to generators in Python
OSCON Byrum
 
Ad

Recently uploaded (20)

Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Aqusag Technologies
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven InsightsAndrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell: Transforming Business Strategy Through Data-Driven Insights
Andrew Marnell
 
Heap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and DeletionHeap, Types of Heap, Insertion and Deletion
Heap, Types of Heap, Insertion and Deletion
Jaydeep Kale
 
Technology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data AnalyticsTechnology Trends in 2025: AI and Big Data Analytics
Technology Trends in 2025: AI and Big Data Analytics
InData Labs
 
What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...What is Model Context Protocol(MCP) - The new technology for communication bw...
What is Model Context Protocol(MCP) - The new technology for communication bw...
Vishnu Singh Chundawat
 
How analogue intelligence complements AI
How analogue intelligence complements AIHow analogue intelligence complements AI
How analogue intelligence complements AI
Paul Rowe
 
Role of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered ManufacturingRole of Data Annotation Services in AI-Powered Manufacturing
Role of Data Annotation Services in AI-Powered Manufacturing
Andrew Leo
 
Cybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure ADCybersecurity Identity and Access Solutions using Azure AD
Cybersecurity Identity and Access Solutions using Azure AD
VICTOR MAESTRE RAMIREZ
 
tecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdftecnologias de las primeras civilizaciones.pdf
tecnologias de las primeras civilizaciones.pdf
fjgm517
 
Drupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy ConsumptionDrupalcamp Finland – Measuring Front-end Energy Consumption
Drupalcamp Finland – Measuring Front-end Energy Consumption
Exove
 
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc Webinar: Consumer Expectations vs Corporate Realities on Data Broker...
TrustArc
 
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep DiveDesigning Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
Designing Low-Latency Systems with Rust and ScyllaDB: An Architectural Deep Dive
ScyllaDB
 
How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?How Can I use the AI Hype in my Business Context?
How Can I use the AI Hype in my Business Context?
Daniel Lehner
 
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptxIncreasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Increasing Retail Store Efficiency How can Planograms Save Time and Money.pptx
Anoop Ashok
 
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes Partner Innovation Updates for May 2025
ThousandEyes
 
Cyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of securityCyber Awareness overview for 2025 month of security
Cyber Awareness overview for 2025 month of security
riccardosl1
 
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-UmgebungenHCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
HCL Nomad Web – Best Practices und Verwaltung von Multiuser-Umgebungen
panagenda
 
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In FranceManifest Pre-Seed Update | A Humanoid OEM Deeptech In France
Manifest Pre-Seed Update | A Humanoid OEM Deeptech In France
chb3
 
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Massive Power Outage Hits Spain, Portugal, and France: Causes, Impact, and On...
Aqusag Technologies
 
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdfSAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
SAP Modernization: Maximizing the Value of Your SAP S/4HANA Migration.pdf
Precisely
 
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdfComplete Guide to Advanced Logistics Management Software in Riyadh.pdf
Complete Guide to Advanced Logistics Management Software in Riyadh.pdf
Software Company
 

A Few of My Favorite (Python) Things

  • 1. A Few of My Favorite Things Mike Pirnat • AG Interactive • CodeMash 2012
  • 2. A Few of My Favorite Things Mike Pirnat • AG Interactive • CodeMash 2012
  • 10. _ ( = 255, lambda V ,B,c :c and Y(V*V+B,B, c -1)if(abs(V)<6)else ( 2+c-4*abs(V)**-0.4)/i ) ;v, x=1500,1000;C=range(v*x );import struct;P=struct.pack;M, j ='<QIIHHHH',open('M.bmp','wb').write for X in j('BM'+P(M,v*x*3+26,26,12,v,x,1,24))or C: i ,Y=_;j(P('BBB',*(lambda T:(T*80+T**9 *i-950*T **99,T*70-880*T**18+701* T **9 ,T*i**(1-T**45*2)))(sum( [ Y(0,(A%3/3.+X%v+(X/v+ A/3/3.-x/2)/1j)*2.5 /x -2.7,i)**2 for A in C [:9]]) /9) ) ) http://preshing.com/20110926/high-resolution-mandelbrot-in-obfuscated-python
  • 12. The Interactive Shell $ python Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) [GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>
  • 13. Docstrings... class Frobulator(object): """It frobulates things.""" def __init__(self, doohickey): """A Frobulator needs a doohickey.""" self.doohickey = doohickey def frobulate(self): """Frobulate ALL the things!""" print "Frobulating..." doodad = self.doohickey() return FrobulatedThing(doodad) class FrobulatedThing(object): """A thing which has been frobulated.""" def __init__(self, thing): """Make a thing into a frobulated thing.""" self.thing = thing
  • 14. ...and Help >>> help(Frobulator) Help on class Frobulator in module frobulator: class Frobulator(__builtin__.object) | It frobulates things. | | Methods defined here: | | __init__(self, doohickey) | A Frobulator needs a doohickey. | | frobulate(self) | Frobulate ALL the things! | ...
  • 15. Comprehensions • List comprehensions • Set comprehensions • Dictionary comprehensions • Generator expressions
  • 16. List Comprehensions x = [item for item in series] x = [do_something(item) for item in series if expression] things = [Thingy.from_data(x) for x in database_results] partiers = [x for x in codemashers if x.slides_done()]
  • 17. List Comprehensions booze = ['beer', 'wine', 'scotch', 'gin'] soft_drinks = ['water', 'soda', 'juice'] a = [(x, y) for x in booze for y in soft_drinks] [('beer', 'water'), ('beer', 'soda'), ('beer', 'juice'), ('wine', 'water'), ('wine', 'soda'), ('wine', 'juice'), ('scotch', 'water'), ('scotch', 'soda'), ('scotch', 'juice'), ('gin', 'water'), ('gin', 'soda'), ('gin', 'juice')]
  • 18. List Comprehensions b = [x for x in zip(booze, soft_drinks)] [('beer', 'water'), ('wine', 'soda'), ('scotch', 'juice')]
  • 19. Set Comprehensions s = {v for v in 'CODEMASH ROCKS' if v not in 'ABCD'} set([' ', 'E', 'H', 'K', 'M', 'O', 'S', 'R'])
  • 20. Dictionary Comprehensions d = {key: value for key, value in list_of_tuples} d = { 'Mike': 'Python', 'Jim': 'Ruby', 'Brad': 'UX', ... } d1 = {val: key for key, val in d.items()} {'Python': 'Mike', 'Ruby': 'Jim', 'UX': 'Brad', ...}
  • 21. Generators def f(how_many): for number in range(how_many): if number**2 > 3: yield number * 2 for number in f(5): print number 4 6 8
  • 22. Generator Expressions gen = (2*x for x in range(5) if x**2 > 3) for number in gen: print number 4 6 8
  • 23. Properties class Foo(object): def __init__(self, bar=42): self.set_bar(bar) def get_bar(self): return self.bar def set_bar(self, bar): self.bar = int(bar)
  • 24. Properties class Foo(object): def __init__(self, bar=42): self.bar = bar @property def bar(self): return self._bar @bar.setter def bar(self, x): self._bar = int(x)
  • 25. Properties class Foo(object): def __init__(self, bar=42): self.bar = bar @property def bar(self): return self._bar @bar.setter def bar(self, x): self._bar = int(x)
  • 26. Properties >>> foo = Foo() >>> foo.bar 42 >>> foo.bar = 'abc' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 9, in bar ValueError: invalid literal for int() with base 10: 'abc'
  • 27. Decorators • That funny-looking @ thing • Similar to Java’s annotations • Replaces a function with a wrapper • Augment functionality in a reusable way
  • 28. Decorators def be_excellent(wrapped): def wrapper(*args, **kwargs): print "Be excellent to each other..." return wrapped(*args, **kwargs) return wrapper @be_excellent def party_on(who): print "...and party on, {0}!".format(who) >>> party_on('dudes') Be excellent to each other... ...and party on, dudes!
  • 29. Context Managers • That funny “with” thing • Simplify calling code that needs setup and teardown • Alternative to try/finally structures • Acquire locks, open and close files, do database transactions, etc.
  • 30. Before Context Managers frobulator = Frobulator(...) try: frobulator.frobulate() finally: frobulator.cleanup()
  • 31. After Context Managers with Frobulator(...) as frobulator: frobulator.frobulate()
  • 32. class Frobulator(object): def __init__(self, ...): ... def __enter__(self): print "Preparing to frobulate..." return self def __exit__(self, exc_type, exc_value, exc_tb): print "Frobulation complete!" def frobulate(self): print "Frobulating!" ...
  • 33. with Frobulator() as frobulator: frobulator.frobulate() Preparing to frobulate... Frobulating! Frobulation complete!
  • 34. import contextlib @contextlib.contextmanager def make_frobulator(): print "Preparing to frobulate..." yield Frobulator() print "Frobulation complete!" with make_frobulator() as frobulator: frobulator.frobulate() Preparing to frobulate... Frobulating! Frobulation complete!
  • 36. Itertools • Tools for iterating on sequences • Inspired by functional languages • Fast and memory efficient • Combine to express more complicated algorithms
  • 37. Itertools: chain from itertools import chain for x in chain([1, 2, 3], [42, 1138, 2112]): print x, 1 2 3 42 1138 2112
  • 38. Itertools: izip from itertools import izip for x in izip([1, 2, 3], [42, 1138, 2112]): print x, (1, 42) (2, 1138) (3, 2112)
  • 39. Itertools: islice from itertools import islice, count for x in islice(count(), 5): print x, for x in islice(count(), 5, 10): print x, for x in islice(count(), 0, 100, 10): print x, 0 1 2 3 4 5 6 7 8 9 0 10 20 30 40 50 60 70 80 90
  • 40. Itertools: islice from itertools import islice, count for x in islice(count(), 5): print x, for x in islice(count(), 5, 10): print x, for x in islice(count(), 0, 100, 10): print x, 0 1 2 3 4 5 6 7 8 9 0 10 20 30 40 50 60 70 80 90
  • 41. Itertools: imap from itertools import imap for thingy in imap(Thingy.from_data, database_results): ...
  • 42. Itertools: cycle from itertools import cycle for x in cycle(['wake up', 'meet Ned', 'romance Rita']): print x wake up meet Ned romance Rita wake up meet Ned romance Rita wake up meet Ned ...
  • 43. Itertools: repeat from itertools import repeat for x in repeat("stop hitting yourself", 5): print x stop hitting yourself stop hitting yourself stop hitting yourself stop hitting yourself stop hitting yourself
  • 44. Functools • Tools for manipulating functions • Partial • Wraps a callable with default arguments • Alternative to lambdas and closures
  • 45. Functools: Partial from functools import partial def f(a, b=2): print a, b f1 = partial(f, 'fixed_a') f2 = partial(f, b='fixed_b') >>> f1(b=1138) fixed_a 1138 >>> f2(1138) 1138 fixed_b
  • 46. Functools: Partial def category_is(category, item): categories = [x.lower() for x in item.categories] if category.lower() in categories: return True return False is_python = partial(category_is, 'python') is_cat_pictures = partial(category_is, 'catpix') ... python_posts = [item for item in blog_posts if is_python(item)] cat_posts = [item for item in blog_posts if is_cat_pictures(item)]
  • 47. Collections • Beyond the basic list, dict, tuple, and set... • Counter • Defaultdict • OrderedDict • Namedtuple • ...and more
  • 48. Counter counter = {} for char in "Hello there, CodeMash!": if char not in counter: counter[char] = 1 else: counter[char] += 1 print counter {'a': 1, ' ': 2, 'C': 1, 'e': 4, 'd': 1, 'H': 1, 'M': 1, 'l': 2, 'o': 2, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1, 'h': 2}
  • 49. Counter counter = {} for char in "Hello there, CodeMash!": if char not in counter: counter[char] = 1 else: counter[char] += 1 print counter {'a': 1, ' ': 2, 'C': 1, 'e': 4, 'd': 1, 'H': 1, 'M': 1, 'l': 2, 'o': 2, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1, 'h': 2}
  • 50. Counter from collections import Counter counter = Counter("Hello there, CodeMash!") print counter Counter({'e': 4, ' ': 2, 'l': 2, 'o': 2, 'h': 2, 'a': 1, 'C': 1, 'd': 1, 'H': 1, 'M': 1, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1})
  • 51. Counter from collections import Counter counter = Counter("Hello there, CodeMash!") print counter Counter({'e': 4, ' ': 2, 'l': 2, 'o': 2, 'h': 2, 'a': 1, 'C': 1, 'd': 1, 'H': 1, 'M': 1, ',': 1, 's': 1, 'r': 1, '!': 1, 't': 1})
  • 52. Namedtuple import math def distance(a, b): return math.sqrt( (a[0] - b[0])**2 + (a[1] - b[1])**2 + (a[2] - b[2])**2 ) a = (1, 2, 3) b = (-1, -2, 42) print distance(a, b) 39.25557285278104
  • 53. Namedtuple from collections import namedtuple Point = namedtuple('Point', 'x y z') def distance(a, b): return math.sqrt( (a.x - b.x)**2 + (a.y - b.y)**2 + (a.z - b.z)**2 ) a = Point(x=1, y=2, z=3) b = Point(-1, -2, 42) print distance(a, b) 39.25557285278104
  • 54. Difflib s1 = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus dui nunc, faucibus id ullamcorper eget, tempus vitae nisl. Donec quis semper risus. Curabitur sit amet tellus eget metus accumsan porta nec nec lorem. Ut vitae sem nisl. Praesent pulvinar feugiat nibh fringilla semper. Nullam cursus tempor lorem ut egestas. Nullam suscipit gravida turpis ac porttitor. Curabitur eleifend augue at risus commodo pretium. Aliquam eget magna risus, ut lobortis metus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam non magna sit amet nulla porttitor molestie sit amet vel sem. Vestibulum sit amet nisl a velit adipiscing porta id non urna. Duis ullamcorper dictum ipsum sit amet congue. """
  • 55. Difflib s2 = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus dui nunc, faucibus id ullamcorper eget, tempus vitae nisl. Donec quis semper risus. Curabitur sit amet tellus eget metus accumsan porta nec nec lorem. Ut vitae sem nisl. Praesent pulvinar feugiat nibh fringilla semper. Nullam cursus tempor lorem ut egestas. Nullam suscipit gravida turpis ac porttitor. Curabitur eleifend augue at risus commodo pretium. Aliquam eget magna risus, ut lobortis montes. Cum sociis natoque penatibus et magnis dis parturient metus, nascetur ridiculus mus. Etiam non magna sit amet nulla porttitor molestie sit amet vel sem. Vestibulum sit amet nisl a velit adipiscing porta id non urna. Duis ullamcorper dictum ipsum sit amet congue. """
  • 56. Difflib import difflib differ = difflib.Differ() diff = differ.compare(s1.splitlines(), s2.splitlines()) print 'n'.join(diff)
  • 57. Difflib Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus dui nunc, faucibus id ullamcorper eget, tempus vitae nisl. Donec quis semper risus. Curabitur sit amet tellus eget metus accumsan porta nec nec lorem. Ut vitae sem nisl. Praesent pulvinar feugiat nibh fringilla semper. Nullam cursus tempor lorem ut egestas. Nullam suscipit gravida turpis ac porttitor. Curabitur eleifend augue at risus commodo pretium. Aliquam eget magna - risus, ut lobortis metus. Cum sociis natoque penatibus ? -- + risus, ut lobortis montes. Cum sociis natoque penatibus ? +++ - et magnis dis parturient montes, nascetur ridiculus mus. ? ^^ ^ + et magnis dis parturient metus, nascetur ridiculus mus. ? ^ ^ Etiam non magna sit amet nulla porttitor molestie sit amet vel sem. Vestibulum sit amet nisl a velit adipiscing porta id non urna. Duis ullamcorper dictum ipsum sit amet congue.
  • 58. Difflib diff = difflib.unified_diff( s1.splitlines(), s2.splitlines(), lineterm='') print 'n'.join(diff)
  • 59. Difflib --- +++ @@ -7,8 +7,8 @@ semper. Nullam cursus tempor lorem ut egestas. Nullam suscipit gravida turpis ac porttitor. Curabitur eleifend augue at risus commodo pretium. Aliquam eget magna -risus, ut lobortis metus. Cum sociis natoque penatibus -et magnis dis parturient montes, nascetur ridiculus mus. +risus, ut lobortis montes. Cum sociis natoque penatibus +et magnis dis parturient metus, nascetur ridiculus mus. Etiam non magna sit amet nulla porttitor molestie sit amet vel sem. Vestibulum sit amet nisl a velit adipiscing porta id non urna. Duis ullamcorper dictum
  • 60. Ast • Use Python to process abstract syntax trees of Python grammar • Helps introspect about what the current grammar looks like • Helps write secure code
  • 61. Ast # Danger: foo = eval(bar) # Safe: foo = ast.literal_eval(bar)
  • 62. Multiprocessing • Like threading, but with subprocesses • Local and remote concurrency • Spawn processes or entire pools • Communicate via queues or pipes • Shared state via shared memory or manager/server process
  • 63. import os from multiprocessing import Process def info(title): print title print 'parent process:', os.getppid() print 'process id:', os.getpid() def f(name): info('function f') print 'hello', name if __name__ == '__main__': info('main') p = Process(target=f, args=('world',)) p.start() p.join()
  • 64. $ python process.py main parent process: 18647 process id: 31317 ---------- function f parent process: 31317 process id: 31318 ---------- hello world
  • 65. import os from multiprocessing import Pool def g(x): info('function g('+str(x)+')') return x * x if __name__ == '__main__': info('main') pool = Pool(2) print pool.map(g, range(100))
  • 66. $ python process.py parent process: 31369 main parent process: 31369 module name: __main__ process id: 31370 parent process: 18647 process id: 31371 process id: 31369 ---------- ---------- ---------- function g(0) function g(4) module name: __main__ module name: __main__ parent process: 31369 parent process: 31369 process id: 31370 function g(14) ---------- process id: 31370 function g(1) module name: __main__ module name: __main__ ---------- parent process: 31369 parent process: 31369 process id: 31370 function g(5) ---------- process id: 31371 function g(13) module name: __main__ function g(2) module name: __main__ ... parent process: 31369 process id: 31370 [0, 1, 4, 9, 16, 25, ..., 8836, ---------- 9025, 9216, 9409, 9604, 9801] module name: __main__ function g(3) module name: __main__
  • 68. Third Party Packages • Most available on PyPI--http://pypi.python.org • pip install packagename • easy_install packagename
  • 69. Virtualenv • Makes an isolated Python environment • Don’t pollute your global site-packages • Insulates Python projects from one another • Don't have to be root
  • 70. Virtualenv $ virtualenv directory $ virtualenv --python=/path/to/specific/python directory $ cd directory $ . bin/activate $ easy_install whatever $ pip install whatever ...do stuff... $ deactivate
  • 71. Datetime and Dateutil • Python’s datetime provides date, time, datetime, and timedelta objects • Dateutil provides powerful extensions • Parsing • Olson-driven timezones • Recurrence
  • 72. Parsing >>> from dateutil.parser import parse >>> parse('01/01/2012') datetime.datetime(2012, 1, 1, 0, 0) >>> parse('2012-01-01') datetime.datetime(2012, 1, 1, 0, 0)
  • 73. Timezones >>> from dateutil import zoneinfo >>> zone = zoneinfo.gettz('US/Eastern') >>> zone tzfile('America/New_York') >>> zone2 = zoneinfo.gettz('US/Hawaii') >>> dt = datetime.now(zone) >>> dt datetime.datetime(2012, 1, 13, 13, 46, 54, 997825, tzinfo=tzfile('America/New_York')) >>> dt.astimezone(zone2) datetime.datetime(2012, 1, 13, 8, 46, 54, 997825, tzinfo=tzfile('Pacific/Honolulu'))
  • 74. Recurrence >>> from dateutil.rrule import rrule, YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, BY_EASTER >>> rr = rrule(YEARLY, dtstart=datetime(1948, 2, 24)) >>> rr.after(datetime(2012, 1, 1)) datetime(2012, 2, 24, 0, 0) >>> rr.between(datetime(2010, 1, 1), datetime(2012, 1, 1)) [datetime(2010, 2, 24, 0, 0), datetime(2011, 2, 24, 0, 0)]
  • 75. howoldismykid.com def periods_between(freq, start_date, end_date):     # dateutil.rrule falls down for monthly recurrences where the start # date's day is greater than the number of days in a subsequent month # in the range; ie, when start date is 10/31/2010, and end date is # 3/13/2011, rrule's between will only produce 2 instances, 12/31 and # 1/31, rather than 4.     if freq == MONTHLY and start_date.day > 28:         start_date = datetime.datetime(start_date.year, start_date.month,                 28, start_date.hour, start_date.minute, start_date.second)     # Same problem but for "Pirates of Penzance" leap day birthdays...     elif freq == YEARLY and is_leap_day(start_date):         start_date = datetime.datetime(start_date.year, start_date.month,                 28, start_date.hour, start_date.minute, start_date.second)     rr = rrule(freq, dtstart=start_date)     periods = len(rr.between(start_date, end_date))     return periods
  • 76. howoldismykid.com >>> start_date = datetime(2007, 9, 10) >>> end_date = datetime(2012, 1, 13) >>> periods_between(YEARLY, start_date, end_date) 4 >>> periods_between(MONTHLY, start_date, end_date) 52 >>> periods_between(WEEKLY, start_date, end_date) 226 >>> periods_between(DAILY, start_date, end_date) 1585
  • 77. Nose • Find, run, and report results of test suites • Low-friction setup • Extendable with plugins (more later) • http://readthedocs.org/docs/nose/en/latest/
  • 78. Nose # test_foo.py def test_a_thing(): assert False def test_another_thing(): assert True
  • 79. Nose $ nosetests tests/test_foo.py F. ====================================================================== FAIL: test_foo.test_a_thing ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/mpirnat/Code/frobulator/lib/python2.7/site-packages/ nose-1.1.2-py2.7.egg/nose/case.py", line 197, in runTest self.test(*self.arg) File "/Users/mpirnat/Code/frobulator/src/frobulator/tests/test_foo.py", line 2, in test_a_thing assert False AssertionError ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1)
  • 80. Nose class TestWhenFrobulating(object): def setup(self): self.frobulator = Frobulator() self.frobulator.frobulate() def test_that_it_frobulated(self): assert self.frobulator.has_frobulated def teardown(self): self.frobulator.cleanup()
  • 82. Nose: Useful Flags • --processes=number • -x • --pdb • --pdb-failures • --failed
  • 83. Nose Plugins • Add custom behavior to your test run • Get coverage statistics (coverage) • Measure cleanliness with PEP-8 (tissue) • Emit human-readable spec-style results (pinocchio) • Or write your own...
  • 84. class TestGeneratesLotsOfFailures(object): def test_generates_failures(self): def _make_a_test(i): # start with some wins if i < 7: assert True # but then it hits the fan... elif i < 30: assert False # then be a little random elif i % 3 == 0: assert False else: assert True for i in range(50): yield _make_a_test, i
  • 85. $ nosetests test_epic_fail.py .......FFFFFFFFFFFFFFFFFFFFFFFF..F..F..F..F..F..F. [lots of test failure output; use your imagination...] -------------------------------------------------------- Ran 50 tests in 0.010s FAILED (errors=30)
  • 87. import os from nose.plugins import Plugin class F7U12(Plugin): name = 'f7u12' enabled = True def options(self, parser, env=os.environ): super(F7U12, self).options(parser, env=env) def configure(self, options, config): super(F7U12, self).configure(options, config) self.config = config if not self.enabled: return
  • 88. def setOutputStream(self, stream): self.stream = stream return self.stream def begin(self): self.failure_count = 0 def handleFailure(self, test, err): self.failure_count += 1 if self.failure_count < 8: self.stream.write('F') else: self.stream.write('U') return True
  • 89. $ nosetests --with-f7u12 test_epic_fail.py .......FFFFFFFFUUUUUUUUUUUUUUUU..U..U..U..U..U..U. [lots of test failure output; use your imagination...] -------------------------------------------------------- Ran 50 tests in 0.010s FAILED (errors=30)
  • 90. Mock • Mock object framework • Avoid writing custom stubs • Uses “Action/Assert” model (not “Record/ Replay”) • Can also patch out module and class attributes in the scope of a test • http://www.voidspace.org.uk/python/mock/
  • 91. Mock from mock import Mock foo = Mock() foo.bar() foo.bar.baz(42) foo.bar.baz.return_value = "whatever" assert foo.bar.called foo.bar.baz.assert_called_with(42)
  • 92. Mock class TestWhenFrobulating(object): def setup(self): self.doohickey = Mock() self.frobulator = Frobulator(self.doohickey) self.frobulator.frobulate() def test_it_uses_the_doohickey(self): assert self.doohickey.called
  • 93. Mock from mock import patch class TestWhenFrobulating(object): @patch('frobulator.DingleHopper') def setup(self, dingle_hopper_class): self.dingle_hopper = Mock() dingle_hopper_class.return_value = self.dingle_hopper self.frobulator = Frobulator() self.frobulator.frobulate() def test_it_uses_a_dingle_hopper(self): assert self.dingle_hopper.called
  • 94. Coverage • Measure coverage of your codebase during program execution • Integrates with several test runners to measure test coverage • http://nedbatchelder.com/code/coverage/
  • 95. #!/usr/bin/env python class Frobulator(object): """It frobulates things.""" def __init__(self, doohickey): """A Frobulator needs a doohickey.""" self.doohickey = doohickey def frobulate(self): """Frobulate ALL the things!""" print "Frobulating..." doodad = self.doohickey() return FrobulatedThing(doodad) class FrobulatedThing(object): """A thing which has been frobulated.""" def __init__(self, thing): """Make a thing into a frobulated thing.""" self.thing = thing if __name__ == '__main__': x = FrobulatedThing(42)
  • 96. #!/usr/bin/env python class Frobulator(object): """It frobulates things.""" def __init__(self, doohickey): """A Frobulator needs a doohickey.""" self.doohickey = doohickey def frobulate(self): """Frobulate ALL the things!""" print "Frobulating..." doodad = self.doohickey() return FrobulatedThing(doodad) class FrobulatedThing(object): """A thing which has been frobulated.""" def __init__(self, thing): """Make a thing into a frobulated thing.""" self.thing = thing if __name__ == '__main__': x = FrobulatedThing(42)
  • 97. $ coverage run frobulator.py $ coverage report -m Name Stmts Miss Cover Missing ------------------------------------------ frobulator 12 4 67% 8, 12-14
  • 98. from mock import Mock, patch from frobulator import Frobulator, FrobulatedThing class TestWhenFrobulating(object): def setup(self): self.doohickey = Mock() self.doohickey.return_value = 42 self.frobulator = Frobulator(self.doohickey) self.result = self.frobulator.frobulate() def test_it_uses_a_doohickey(self): assert self.doohickey.called def test_it_returns_a_frobulated_thing(self): assert isinstance(self.result, FrobulatedThing)
  • 99. $ nosetests --with-coverage --cover-package frobulator .. Name Stmts Miss Cover Missing ------------------------------------------ frobulator 12 1 92% 26 ------------------------------------------ Ran 2 tests in 0.008s OK
  • 100. Useful Flags • --cover-erase • --cover-inclusive • --cover-tests
  • 101. Lettuce • Like Cucumber • BDD test framework • Natural language augmented by code • Big wins pairing Devs + QA + Biz • http://lettuce.it/
  • 102. Lettuce Vocabulary • Features • Scenarios • Steps • World • Terrain
  • 103. Feature: The website has a homepage In order to demo Lettuce As a presenter I want to test the homepage of a website Scenario: Verify the site is up Given I access the url "http://localhost:8000/" Then I get a status "200"
  • 104. from lettuce import step, world from nose.tools import assert_equals import requests @step(r'I access the url "(.*)"') def access_url(step, url): world.response = requests.get(url) @step(r'I get a status "(.*)"') def get_status(step, expected_status): expected_status = int(expected_status) assert_equals(world.response.status_code, expected_status)
  • 105. Snake-Guice • Framework for Dependency Injection • Reduce coupling! • Improve testability! • http://code.google.com/p/snake-guice/
  • 106. Snake-Guice • Bind identifiers to things you want to inject • Decorate code with injection hints • Use injector to get instance with all dependencies resolved and injected • Construct with mocks in tests, minimize the need for patching
  • 107. Define the Identifier class IFrobulator(object): pass
  • 108. Decorate Your Code from snakeguice import inject class WankelRotator(object): @inject(frobulator=IFrobulator) def __init__(self, frobulator): self.frobulator = frobulator
  • 109. Decorate Your Code from snakeguice import inject class WankelRotator(object): @inject(frobulator=IFrobulator) def __init__(self, frobulator): self.frobulator = frobulator
  • 110. Configure Bindings from frobulator import Frobulator class BindingModule(object): def configure(self, binder): binder.bind(IFrobulator, to=Frobulator)
  • 111. Get an Instance from snakeguice import Injector import WankelRotator injector = Injector(BindingModule()) rotator = injector.get_instance(WankelRotator)
  • 112. Requests • A human-friendly alternative to urllib2 • Maturing rapidly • http://python-requests.org/
  • 113. Using Requests import requests # Authentication! r = requests.get('https://api.github.com', auth=('user', 'pass')) print r.status_code print r.headers['content-type']
  • 114. Using Requests # Posting name-value pair form data post_data = {'foo': 'bar', 'baz': 'quux', ...} r = requests.post(url, data=post_data) # Posting a glob of JSON r = requests.post(url, data=json.dumps(post_data)) # Multipart file attachment files = {'my_file.xls': open('my_file.xls', 'rb')} r = requests.post(url, files=files)
  • 115. Using Requests # Custom headers! headers = {'X-foo': 'bar'} r = requests.get(url, headers=headers) # Cookies! cookies = {'a_cookie': 'is delicious'} r = requests.get(url, cookies=cookies)
  • 116. Pylons • http://docs.pylonsproject.org/en/latest/docs/ pylons.html • MVCish web framework • Glues together several component projects • Can use your preferred components • Somewhat dead (evolved into Pyramid)
  • 117. Pylons • Request/response: webob • URL dispatch: routes • Input validation: formencode • Persistence/ORM: sqlalchemy • Session: beaker • Templates: mako
  • 118. from routes import Mapper def make_map(config): """Create, configure and return the routes Mapper""" map = Mapper(directory=config['pylons.paths']['controllers'], always_scan=config['debug']) ... map.connect('/', controller='main', action='index') map.connect('/contact', controller='contact', action='index', conditions={'method':'GET'}) map.connect('/contact', controller='contact', action='send', conditions={'method':'POST'}) return map
  • 119. from howoldismykid.lib.base import BaseController, render class MainController(BaseController): def index(self): # Return a rendered template return render('/main.mako')
  • 120. from formencode import Schema, validators class ContactForm(Schema): email = validators.Email(not_empty=True) subject = validators.String(not_empty=True) message = validators.String(not_empty=True)
  • 121. from pylons.decorators import validate from howoldismykid.lib.base import BaseController, render from howoldismykid.model.forms import ContactForm class ContactController(BaseController): def __init__(self, *args, **kwargs): BaseController.__init__(self, *args, **kwargs) self.emailer = Emailer(SMTP, USER, PW, FAKE_EMAIL) def index(self): # Return a rendered template return render('/contact.mako') @validate(schema=ContactForm(), form="index", prefix_error=False) def send(self): validated = self.form_result self.emailer.send_mail(validated['email'], EMAIL, validated['subject'], validated['message']) return render('/contact_done.mako')
  • 122. <!DOCTYPE HTML> <html> <head> ${self.head_tags()} ... </head> <body> <div id="header">...</div> <div id="content"> ${self.body()} </div> <div id="footer">...</div> <%include file="google_analytics.mako"/> ${self.foot_tags()} </body> </html>
  • 123. <%inherit file="/base.mako" /> <%def name="head_tags()"> <title>How Old Is My Kid?</title> </%def> <h2>Contact Us</h2> <p>Suggest a new feature, let us know how we're doing, or just say hi.</p> <form method="POST" action="/contact" id="contact-form"> <p><label for="email">Email:</label> <input type="text" name="email" id="email" /></p> <p><label for="subject">Subject:</label> <input type="text" name="subject" id="subject" /></p> <p><label for="message">Message:</label><br /> <textarea name="message" id="message"></textarea></p> <p><input type="submit" value="Submit" /></p> </form> <%def name="foot_tags()"> <script type="text/javascript"> $(document).ready(function() { $("button, input:submit").button(); }); </script> </%def>
  • 124. Django • https://www.djangoproject.com/ • Full stack/harder to replace components • Lots of reusable apps • Admin interface • Lots of deployment options (Google) • Not dead
  • 125. from django.conf.urls.defaults import patterns, url urlpatterns = patterns('', url(r'^/$', 'howoldismykid.views.main', name='main'), url(r'^/contact/$', 'howoldismykid.views.contact', name='contact'), )
  • 126. from django.shortcuts import render def main(request): return render(request, 'main.html')
  • 127. from django import forms class ContactForm(forms.Form): email = forms.EmailField(label='Email Address') subject = forms.CharField(label='Subject') message = forms.CharField(label='Message', widget=forms.Textarea)
  • 128. from contact.forms import ContactForm from django.shortcuts import render def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): emailer = Emailer(SMTP, USER, PW, FAKE_EMAIL) emailer.send_mail( form.cleaned_data['email'], EMAIL, form.cleaned_data['subject'], form.cleaned_data['message']) return render(request, 'contact_done.html') else: form = ContactForm() return render(request, 'contact.html', {'form': form })
  • 129. <!DOCTYPE HTML> <html> <head> {% block head_tags %}...{% endblock %} ... </head> <body> <div id="header">...</header> <div id="content"> {% block content %}It goes here.{% endblock %} </div> <div id="footer">...</div> {% include "google_analytics.html" %} {% block foot_tags %}{% endblock %} </body> </html>
  • 130. {% extends 'base.html' %} {% block head_tags %} <title>How Old Is My Kid?</title> {% endblock %} {% block content %} <h2>Contact Us</h2> <p>Suggest a new feature, let us know how we're doing, or just say hi.</p> <form method="POST" action="/contact" id="contact-form"> {% csrf_token %} {{ form.as_p }} <p><input type="submit" value="Submit" /></p> </form> {% endblock %} {% block foot_tags %} <script type="text/javascript"> $(document).ready(function() { $("button, input:submit").button(); }); </script> {% endblock %}
  • 132. Planet Python • http://planet.python.org/ • Aggregate feed of Python blogs • Great way to follow what's going on • Minimize newsgroup/mailing list burdens • Easy to be included
  • 133. The Python Ecosystem • http://mirnazim.org/writings/python- ecosystem-introduction/ • Great introduction to the Python ecosystem • Everything you need to get up and running
  • 134. The Hitchhiker’s Guide • http://docs.python-guide.org/ • Opinionated advice about using Python • Basics • Scenario-specific details and recommendations
  • 135. PyMotW • Explored a different standard library module every week • Examples, examples, examples • http://www.doughellmann.com/PyMOTW/ • The Python Standard Library by Example http://www.doughellmann.com/books/byexample/
  • 136. Podcasts • http://www.radiofreepython.com/ • http://frompythonimportpodcast.com/ • http://djangodose.com/ • http://advocacy.python.org/podcasts/ • http://www.awaretek.com/python/ • Start your own! Be the change you want...
  • 137. PyOhio • Free as in $0.00 • Columbus, Ohio • Last weekend in July • http://pyohio.org
  • 138. PyCon • Great people • Great vibe • All volunteer–personal ownership • Video! http://pycon.blip.tv/ • 2012 & 2013: Santa Clara • 2014 & 2015: Montreal
  • 139. TiP BoF • Testing in Python Birds of a Feather • Lightning Talks • Heckling...
  • 141. The Zen • Guiding principles • Sage advice • >>> import this
  • 142. The Zen • Beautiful is better than ugly. • Readability counts. • Explicit is better than • Special cases aren't special implicit. enough to break the rules. • Simple is better than • Although practicality beats complex. purity. • Complex is better than • Errors should never pass complicated. silently. • Flat is better than nested. • Unless explicitly silenced. • Sparse is better than dense.
  • 143. The Zen • In the face of ambiguity, • Although never is often refuse the temptation to better than right now. guess. • If the implementation is • There should be one– hard to explain, it's a bad and preferably only one– idea. obvious way to do it. • If the implementation is • Although that way may not easy to explain, it may be a be obvious at first unless good idea. you're Dutch. • Namespaces are one • Now is better than never. honking great idea -- let's do more of those!
  • 145. Fin • Twitter: @mpirnat • Blog: http://mike.pirnat.com • Win a special prize–name all the movies • Thanks for coming!