I'm Wil Langford. I like math, Python, and games.
This talk is located in my DecoratorsTalk2015 repository at:
https://github.com/wil-langford/DecoratorsTalk2015 (or http://goo.gl/AAJ7U0 for short)
To prepare for the talk, please clone the repository and load the iPython notebook. Let me know if you need any help with this step.
@propertyBefore we go any further, we need to choose a super-secure password.
In [ ]:
global PASSWORD
PASSWORD = "Guild o' Code"
In [ ]:
def halver(num):
"""Returns half of the 'num' argument.""" # docstring
return num / 2
In [ ]:
print "halver's name:", halver.__name__
print "halver's docstring:", halver.__doc__
In [ ]:
halver?
In [ ]:
print halver(20)
In [ ]:
print halver(10)
Uh-oh...
In [ ]:
print halver(5)
In [ ]:
print [i/2 for i in range(10)]
In [ ]:
print [i/2.0 for i in range(10)]
In [ ]:
print [float(i)/2 for i in range(10)]
In [ ]:
def float_wrapper(func):
def wrapper(float_me):
return func(float(float_me))
return wrapper
In [ ]:
print float_wrapper(halver)(10)
print float_wrapper(halver)(5)
In [ ]:
halve = float_wrapper(halver)
In [ ]:
print halver(10)
print halver(5)
In [ ]:
def halver(num):
"""Returns half of the 'num' argument.
This is a reimplementation of halver()."""
return num / 2
halver = float_wrapper(halver)
In [ ]:
print halve(5)
In [ ]:
@float_wrapper
def halver2(num):
"""Returns half of the 'num' argument.
This is a re-reimplementation of halver()."""
return num / 2
In [ ]:
print halver2(5)
In [ ]:
print "halver's name:", halver.__name__
print "halver's docstring:", halver.__doc__
print "halver2's name:", halver2.__name__
print "halver2's docstring:", halver2.__doc__
In [ ]:
halver?
In [ ]:
import functools
def better_float_wrapper(func):
@functools.wraps(func) # this line is the only difference
def wrapper(num):
return func(float(num))
return wrapper
In [ ]:
@better_float_wrapper
def halver3(num):
"""Returns half of the 'num' argument.
This is a re-reimplementation of halve()."""
return num / 2
In [ ]:
print halver3(5)
print "halver3's name:", halver3.__name__
print "halver3's docstring:", halver3.__doc__
In [ ]:
halver3?
In [ ]:
class StrictAttributeHolder(object):
def __init__(self):
self._int_val = None
@property
def int_val(self):
if self._int_val is not None:
return self._int_val
else:
raise Exception("Can't read what isn't written!")
@int_val.setter
def int_val(self, value):
if isinstance(value, int):
self._int_val = value
else:
raise TypeError("Can't set int_val to a non-int value!")
In [ ]:
sah = StrictAttributeHolder()
In [ ]:
print sah.int_val
In [ ]:
sah.int_val = 5
In [ ]:
print sah.int_val
In [ ]:
sah.int_val = 5.0
In [ ]:
sah.int_val = [5]
In [ ]:
# Create a @timed_function decorator that computes and prints the execution time of
# any function that it wraps. Use *args and **kwargs to capture all function
# arguments.
def timed_function(func):
# Your implementation here
pass
In [ ]:
# Create a @case_mod decorator that gives any function that it wraps an
# all-lowercase version of an input string and then returns an all-uppercase
# version of the wrapped function's output
def case_mod(func):
# Your implementation here
pass
In [ ]:
# Create a @secured_function decorator that looks for a global password before
# running the wrapped function and will raise an exception instead of running
# the wrapped function if the wrong password is provided. Use *args and **kwargs
# capture all function arguments.
def timed_function(func):
global PASSWORD
# Your implementation here
pass
In [ ]:
# Execute this cell without modifying it.
picky_eater_food = "You can now write your own decorators!".split(' ')
@secured_function
@timed_function
@case_mod
def picky_eater(food):
if food.islower():
time.sleep(0.1 * len(food))
return food
else:
raise Exception("I don't wanna eat this!")
In [ ]:
# Change ONLY the assigned value of PASSWORD in this cell, then
# execute it.
global PASSWORD
PASSWORD = ''
In [ ]:
# Run this cell as-is without any exceptions cropping up and with
# an execution time printed out for each morsel in picky_eater_food.
for morsel in picky_eater_food:
print picky_eater(morsel)
@propertydescriptor protocol
__get__() method__set__() method__del__() methodobject attribute access