CPL: Decorators to Decorators
A study of higher order functions
Abdirahman Ahmed Osman
Pre-class
Consider theto_bin()andcount_forever()generator functions from class - to_bin(it)returns an iterable that converts every item from it to its binary rep- resentation -count_forever(start = 0)return an iterable that yieldsstart, start + 1,start + 2…
For each snippet, indicate whether it terminates or not
to_bin(count_forever())
(bin(x) for x in count_forever())
{x: bin(x) for x in count_forever()}
Define a function count and a variable init so thatreduce(count,my_list, init) would return a dictionary indicating the number of times each item occurs inmy_list.
from functools import reduce
# count definition
# init assignment
my_list = ['they','were', 'the', ....,'times']
reduce(count_my_list, init)
# {"best":1,"worst":1,"they":2...}
Decorators and such
def time_this(func): def wrapper(*args, kwargs): start = time.time() retval = func(*args, **kwargs) stop = time.time() print(“{} took {:0.3f}sec”.format(func.__name__, stop-start)) **return retval return wrapper
@time_this def add5(x): time.sleep(1.0) return x + 5
add5(10) _# return 15
print:
add5 took 1.001 sec_
deff add10(x): time.sleep(2.0) return x + 10
add10 = time_this(add10) # same as putting @time_this before the function definition
Fun facts
- The@syntax is syntactic sugar forfunc = dec(func)
- You can stack multiple decorators! @ @ def func(): pass
- You can decorate decorators
- A decorator will clobber a wrapper function’s docstrings,name, and other special attributes. - Usefunctools.wrapsto avoid this ∗it moves special attributes from function to the new wrapped function
Validation
@validate_int def prompt_for_age(): return input(“Enter your age:”)
prompt_for_age() _# Enter your age: bob
Requires int!
Enter your age: 1_
Now let’s buildvallidate_int(func)
import functools
def validate_int(func): @functools.wraps(func) def wrapper(args,kwargs): **while True: try : integer_value == int(func(args,kwargs)) **return integer_value except ValueError: print(‘Requires int!”) return wrapper
Let’s make it more general
def validate(const=int): def decorator(func): def wrapper(args,kwargs): **while True: try : return const(func(args, kwargs)) **except ValueError: print(“Invalid value”) return wrapper return decorator
@validate(float) def prompt_for_age(): return input(“Enter your age: “)
# same as prompt_for_age = validate(float)(prompt_for_age)
Packages
- Structure a python’s module namespace using “dotted module names” main.py classroom/ init.py
utilities.py
modles/
__init__.py
assignment.py
- Inmain.py
import classroom.utilities
import classroom.modles.assignment
from classroom.models.assignment import Assignment
classroom.utilites.grade()
a = Assignment()