updated contents from Atlas repo
This commit is contained in:
33
decorators/average.py
Normal file
33
decorators/average.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
>>> avg = make_averager()
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
>>> avg.__code__.co_varnames
|
||||
('new_value', 'total')
|
||||
>>> avg.__code__.co_freevars
|
||||
('series',)
|
||||
>>> avg.__closure__ # doctest: +ELLIPSIS
|
||||
(<cell at 0x...: list object at 0x...>,)
|
||||
>>> avg.__closure__[0].cell_contents
|
||||
[10, 11, 12]
|
||||
"""
|
||||
|
||||
DEMO = """
|
||||
>>> avg.__closure__
|
||||
(<cell at 0x107a44f78: list object at 0x107a91a48>,)
|
||||
"""
|
||||
|
||||
|
||||
def make_averager():
|
||||
series = []
|
||||
|
||||
def averager(new_value):
|
||||
series.append(new_value)
|
||||
total = sum(series)
|
||||
return total/len(series)
|
||||
|
||||
return averager
|
||||
20
decorators/average_broken.py
Normal file
20
decorators/average_broken.py
Normal file
@@ -0,0 +1,20 @@
|
||||
"""
|
||||
>>> avg = make_averager()
|
||||
>>> avg(10)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
UnboundLocalError: local variable 'num_items' referenced before assignment
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def make_averager():
|
||||
num_items = 0
|
||||
total = 0
|
||||
|
||||
def averager(new_value):
|
||||
num_items += 1
|
||||
total += new_value
|
||||
return total / num_items
|
||||
|
||||
return averager
|
||||
45
decorators/average_fixed.py
Normal file
45
decorators/average_fixed.py
Normal file
@@ -0,0 +1,45 @@
|
||||
"""
|
||||
>>> avg = make_averager()
|
||||
>>> other_avg = make_averager()
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
>>> avg.__code__.co_varnames
|
||||
('new_value',)
|
||||
>>> avg.__code__.co_freevars
|
||||
('num_items', 'total')
|
||||
>>> avg.__closure__ # doctest: +ELLIPSIS
|
||||
(<cell at 0x...: int object at 0x...>, <cell at 0x...: int object at 0x...>)
|
||||
>>> avg.__closure__[0].cell_contents
|
||||
3
|
||||
>>> avg.__closure__[1].cell_contents
|
||||
33
|
||||
>>> other_avg(5)
|
||||
5.0
|
||||
>>> other_avg(10)
|
||||
7.5
|
||||
>>> other_avg(15)
|
||||
10.0
|
||||
"""
|
||||
|
||||
DEMO = """
|
||||
>>> avg.__closure__
|
||||
(<cell at 0x10fd24f78: int object at 0x10f6d3db0>,
|
||||
<cell at 0x10fd24d38: int object at 0x10f6d4170>)
|
||||
"""
|
||||
|
||||
|
||||
def make_averager():
|
||||
num_items = 0
|
||||
total = 0
|
||||
|
||||
def averager(new_value):
|
||||
nonlocal num_items, total
|
||||
num_items += 1
|
||||
total += new_value
|
||||
return total / num_items
|
||||
|
||||
return averager
|
||||
39
decorators/average_fixed_py2.py
Normal file
39
decorators/average_fixed_py2.py
Normal file
@@ -0,0 +1,39 @@
|
||||
"""
|
||||
>>> avg = make_averager()
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
>>> avg.__code__.co_varnames
|
||||
('new_value',)
|
||||
>>> avg.__code__.co_freevars
|
||||
('ns',)
|
||||
>>> avg.__closure__ # doctest: +ELLIPSIS
|
||||
(<cell at 0x...: Namespace object at 0x...>,)
|
||||
>>> avg.__closure__[0].cell_contents.__dict__
|
||||
{'total': 33, 'num_items': 3}
|
||||
"""
|
||||
|
||||
DEMO = """
|
||||
>>> avg.__closure__
|
||||
(<cell at 0x108df5980: Namespace object at 0x108e06790>,)
|
||||
"""
|
||||
|
||||
|
||||
class Namespace(object):
|
||||
pass
|
||||
|
||||
|
||||
def make_averager():
|
||||
ns = Namespace()
|
||||
ns.num_items = 0
|
||||
ns.total = 0
|
||||
|
||||
def averager(new_value):
|
||||
ns.num_items += 1
|
||||
ns.total += new_value
|
||||
return float(ns.total) / ns.num_items
|
||||
|
||||
return averager
|
||||
21
decorators/average_oo.py
Normal file
21
decorators/average_oo.py
Normal file
@@ -0,0 +1,21 @@
|
||||
"""
|
||||
>>> avg = Averager()
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class Averager():
|
||||
|
||||
def __init__(self):
|
||||
self.series = []
|
||||
|
||||
def __call__(self, new_value):
|
||||
self.series.append(new_value)
|
||||
total = sum(self.series)
|
||||
return total/len(self.series)
|
||||
34
decorators/average_partial.py
Normal file
34
decorators/average_partial.py
Normal file
@@ -0,0 +1,34 @@
|
||||
"""
|
||||
>>> import functools
|
||||
>>> avg = functools.partial(averager, series=[])
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
>>> avg.args
|
||||
()
|
||||
>>> avg.keywords
|
||||
{'series': [10, 11, 12]}
|
||||
>>> avg.func # doctest: +ELLIPSIS
|
||||
<function averager at 0x...>
|
||||
>>> avg.func.__code__.co_varnames
|
||||
('new_value', 'series', 'total')
|
||||
"""
|
||||
|
||||
DEMO = """
|
||||
>>> avg.func
|
||||
<function averager at 0x1010c5560>
|
||||
>>> avg.func.__code__.co_varnames
|
||||
('new_value',)
|
||||
>>> avg.__code__.co_freevars
|
||||
('num_items', 'total')
|
||||
>>> avg.__closure__
|
||||
"""
|
||||
|
||||
def averager(new_value, series):
|
||||
series.append(new_value)
|
||||
total = sum(series)
|
||||
return float(total)/len(series)
|
||||
|
||||
28
decorators/average_py2.py
Normal file
28
decorators/average_py2.py
Normal file
@@ -0,0 +1,28 @@
|
||||
"""
|
||||
>>> avg = make_averager()
|
||||
>>> avg(10)
|
||||
10.0
|
||||
>>> avg(11)
|
||||
10.5
|
||||
>>> avg(12)
|
||||
11.0
|
||||
>>> avg.__code__.co_varnames
|
||||
('new_value', 'total')
|
||||
>>> avg.__code__.co_freevars
|
||||
('series',)
|
||||
>>> avg.__closure__ # doctest: +ELLIPSIS
|
||||
(<cell at 0x...: list object at 0x...>,)
|
||||
>>> avg.__closure__[0].cell_contents
|
||||
[10, 11, 12]
|
||||
"""
|
||||
|
||||
|
||||
def make_averager():
|
||||
series = []
|
||||
|
||||
def averager(new_value):
|
||||
series.append(new_value)
|
||||
total = sum(series)
|
||||
return float(total)/len(series)
|
||||
|
||||
return averager
|
||||
15
decorators/clockdeco.py
Normal file
15
decorators/clockdeco.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# clockdeco.py
|
||||
|
||||
import time
|
||||
|
||||
|
||||
def clock(func):
|
||||
def clocked(*args):
|
||||
t0 = time.time()
|
||||
result = func(*args)
|
||||
elapsed = time.time() - t0
|
||||
name = func.__name__
|
||||
arg_str = ', '.join(repr(arg) for arg in args)
|
||||
print('[%0.8fs] %s(%s) -> %r' % (elapsed, name, arg_str, result))
|
||||
return result
|
||||
return clocked
|
||||
23
decorators/clockdeco2.py
Normal file
23
decorators/clockdeco2.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# clockdeco2.py
|
||||
|
||||
import time
|
||||
import functools
|
||||
|
||||
|
||||
def clock(func):
|
||||
@functools.wraps(func)
|
||||
def clocked(*args, **kwargs):
|
||||
t0 = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
elapsed = time.time() - t0
|
||||
name = func.__name__
|
||||
arg_lst = []
|
||||
if args:
|
||||
arg_lst.append(', '.join(repr(arg) for arg in args))
|
||||
if kwargs:
|
||||
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
|
||||
arg_lst.append(', '.join(pairs))
|
||||
arg_str = ', '.join(arg_lst)
|
||||
print('[%0.8fs] %s(%s) -> %r ' % (elapsed, name, arg_str, result))
|
||||
return result
|
||||
return clocked
|
||||
31
decorators/clockdeco2_demo.py
Normal file
31
decorators/clockdeco2_demo.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# clockdec2o_demo.py
|
||||
|
||||
"""
|
||||
>>> pythagoras(3, 4) # doctest: +ELLIPSIS
|
||||
[0.0...s] pythagoras(3, 4) -> 5.0
|
||||
5.0
|
||||
>>> pythagoras(9, h=15) # doctest: +ELLIPSIS
|
||||
[0.0...s] pythagoras(9, h=15) -> 12.0
|
||||
12.0
|
||||
|
||||
"""
|
||||
import time
|
||||
import math
|
||||
from clockdeco2 import clock
|
||||
|
||||
|
||||
@clock
|
||||
def pythagoras(a, b=None, h=None):
|
||||
if b is None and h is None:
|
||||
raise TypeError('must provide second leg (b) or hypotenuse (h)')
|
||||
if h is None:
|
||||
return math.sqrt(a*a + b*b)
|
||||
else:
|
||||
return math.sqrt(h*h - a*a)
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
print('*' * 40, 'Calling pythagoras(3, 4)')
|
||||
pythagoras(3, 4)
|
||||
print('*' * 40, 'Calling pythagoras(9, h=15)')
|
||||
pythagoras(9, h=15)
|
||||
95
decorators/clockdeco2_tests.py
Normal file
95
decorators/clockdeco2_tests.py
Normal file
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
>>> f_empty()
|
||||
[0.0...s] f_empty() -> None
|
||||
>>> f_args('spam', 3)
|
||||
[0.0...s] f_args('spam', 3) -> 'spamspamspam'
|
||||
'spamspamspam'
|
||||
>>> snooze(1234)
|
||||
[1...s] snooze(1234) -> None
|
||||
>>> average(1, 2, 3)
|
||||
[0.0...s] average(1, 2, 3) -> 2.0
|
||||
2.0
|
||||
>>> average(*range(10**3))
|
||||
[0.0...s] average(0, 1, ..., 999) -> 499.5
|
||||
499.5
|
||||
>>> factorial(10)
|
||||
[0.000...s] factorial(1) -> 1
|
||||
[0.000...s] factorial(2) -> 2
|
||||
[0.000...s] factorial(3) -> 6
|
||||
[0.000...s] factorial(4) -> 24
|
||||
[0.000...s] factorial(5) -> 120
|
||||
[0.000...s] factorial(6) -> 720
|
||||
[0.000...s] factorial(7) -> 5040
|
||||
[0.000...s] factorial(8) -> 40320
|
||||
[0.000...s] factorial(9) -> 362880
|
||||
[0.000...s] factorial(10) -> 3628800
|
||||
3628800
|
||||
>>> fibonacci(1)
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
1
|
||||
>>> fibonacci(5)
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(3) -> 2
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(3) -> 2
|
||||
[0.000...s] fibonacci(4) -> 3
|
||||
[0.000...s] fibonacci(5) -> 5
|
||||
5
|
||||
>>> f_kwargs(3, 5, d='spam', c='eggs')
|
||||
[0.0...s] f_kwargs(3, 5, c='eggs', d='spam') -> 15
|
||||
15
|
||||
>>> f_args.__name__
|
||||
'f_args'
|
||||
>>> f_kwargs.__name__
|
||||
'f_kwargs'
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from clockdeco2 import clock
|
||||
|
||||
@clock
|
||||
def f_empty():
|
||||
pass
|
||||
|
||||
@clock
|
||||
def f_args(a, b):
|
||||
return a*b
|
||||
|
||||
@clock
|
||||
def snooze(milis):
|
||||
time.sleep(milis/1000)
|
||||
|
||||
@clock
|
||||
def average(*args):
|
||||
return sum(args) / len(args)
|
||||
|
||||
@clock
|
||||
def factorial(n):
|
||||
return 1 if n < 2 else n*factorial(n-1)
|
||||
|
||||
@clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
@clock
|
||||
def f_kwargs(a, b, c=1, d='eggs'):
|
||||
from time import sleep
|
||||
sleep(0.001)
|
||||
return a*b
|
||||
|
||||
|
||||
|
||||
import doctest
|
||||
doctest.testmod(optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
|
||||
18
decorators/clockdeco_demo.py
Normal file
18
decorators/clockdeco_demo.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# clockdeco_demo.py
|
||||
|
||||
import time
|
||||
from clockdeco import clock
|
||||
|
||||
@clock
|
||||
def snooze(seconds):
|
||||
time.sleep(seconds)
|
||||
|
||||
@clock
|
||||
def factorial(n):
|
||||
return 1 if n < 2 else n*factorial(n-1)
|
||||
|
||||
if __name__=='__main__':
|
||||
print('*' * 40, 'Calling snooze(.123)')
|
||||
snooze(.123)
|
||||
print('*' * 40, 'Calling factorial(6)')
|
||||
print('6! =', factorial(6))
|
||||
22
decorators/clockdeco_demo2.py
Normal file
22
decorators/clockdeco_demo2.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from clockdeco import clock
|
||||
|
||||
import time
|
||||
|
||||
@clock
|
||||
def snooze(milis):
|
||||
time.sleep(milis/1000)
|
||||
|
||||
@clock
|
||||
def factorial(n):
|
||||
return 1 if n < 2 else n*factorial(n-1)
|
||||
|
||||
|
||||
@clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
snooze(123)
|
||||
print(factorial(6))
|
||||
print(fibonacci(4))
|
||||
20
decorators/clockdeco_demo3.py
Normal file
20
decorators/clockdeco_demo3.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import functools
|
||||
from clockdeco import clock
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
@clock
|
||||
def factorial(n):
|
||||
return 1 if n < 2 else n*factorial(n-1)
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
@clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
|
||||
print(factorial(6))
|
||||
print(fibonacci(6))
|
||||
40
decorators/clockdeco_param.py
Normal file
40
decorators/clockdeco_param.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# clockdeco_param.py
|
||||
|
||||
"""
|
||||
>>> snooze(.1) # doctest: +ELLIPSIS
|
||||
[0.101...s] snooze(0.1) -> None
|
||||
>>> clock('{name}: {elapsed}')(time.sleep)(.2) # doctest: +ELLIPSIS
|
||||
sleep: 0.20...
|
||||
>>> clock('{name}({args}) dt={elapsed:0.3f}s')(time.sleep)(.2)
|
||||
sleep(0.2) dt=0.201s
|
||||
"""
|
||||
|
||||
# BEGIN CLOCKDECO_PARAM
|
||||
import time
|
||||
|
||||
DEFAULT_FMT = '[{elapsed:0.8f}s] {name}({args}) -> {result}'
|
||||
|
||||
def clock(fmt=DEFAULT_FMT): # <1>
|
||||
def decorate(func): # <2>
|
||||
def clocked(*_args): # <3>
|
||||
t0 = time.time()
|
||||
_result = func(*_args) # <4>
|
||||
elapsed = time.time() - t0
|
||||
name = func.__name__
|
||||
args = ', '.join(repr(arg) for arg in _args) # <5>
|
||||
result = repr(_result) # <6>
|
||||
print(fmt.format(**locals())) # <7>
|
||||
return _result # <8>
|
||||
return clocked # <9>
|
||||
return decorate # <10>
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@clock() # <11>
|
||||
def snooze(seconds):
|
||||
time.sleep(seconds)
|
||||
|
||||
for i in range(3):
|
||||
snooze(.123)
|
||||
|
||||
# END CLOCKDECO_PARAM
|
||||
9
decorators/clockdeco_param_demo1.py
Normal file
9
decorators/clockdeco_param_demo1.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import time
|
||||
from clockdeco_param import clock
|
||||
|
||||
@clock('{name}: {elapsed}s')
|
||||
def snooze(seconds):
|
||||
time.sleep(seconds)
|
||||
|
||||
for i in range(3):
|
||||
snooze(.123)
|
||||
9
decorators/clockdeco_param_demo2.py
Normal file
9
decorators/clockdeco_param_demo2.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import time
|
||||
from clockdeco_param import clock
|
||||
|
||||
@clock('{name}({args}) dt={elapsed:0.3f}s')
|
||||
def snooze(seconds):
|
||||
time.sleep(seconds)
|
||||
|
||||
for i in range(3):
|
||||
snooze(.123)
|
||||
82
decorators/clockdeco_tests.py
Normal file
82
decorators/clockdeco_tests.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
>>> f_empty()
|
||||
[0.0...s] f_empty() -> None
|
||||
>>> f_args('spam', 3)
|
||||
[0.0...s] f_args('spam', 3) -> 'spamspamspam'
|
||||
'spamspamspam'
|
||||
>>> snooze(1234)
|
||||
[1...s] snooze(1234) -> None
|
||||
>>> average(1, 2, 3)
|
||||
[0.0...s] average(1, 2, 3) -> 2.0
|
||||
2.0
|
||||
>>> average(*range(10**3))
|
||||
[0.0...s] average(0, 1, ..., 999) -> 499.5
|
||||
499.5
|
||||
>>> factorial(10)
|
||||
[0.000...s] factorial(1) -> 1
|
||||
[0.000...s] factorial(2) -> 2
|
||||
[0.000...s] factorial(3) -> 6
|
||||
[0.000...s] factorial(4) -> 24
|
||||
[0.000...s] factorial(5) -> 120
|
||||
[0.000...s] factorial(6) -> 720
|
||||
[0.000...s] factorial(7) -> 5040
|
||||
[0.000...s] factorial(8) -> 40320
|
||||
[0.000...s] factorial(9) -> 362880
|
||||
[0.000...s] factorial(10) -> 3628800
|
||||
3628800
|
||||
>>> fibonacci(1)
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
1
|
||||
>>> fibonacci(5)
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(3) -> 2
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(0) -> 0
|
||||
[0.000...s] fibonacci(1) -> 1
|
||||
[0.000...s] fibonacci(2) -> 1
|
||||
[0.000...s] fibonacci(3) -> 2
|
||||
[0.000...s] fibonacci(4) -> 3
|
||||
[0.000...s] fibonacci(5) -> 5
|
||||
5
|
||||
>>> f_args.__name__
|
||||
'clocked'
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
from clockdeco import clock
|
||||
|
||||
@clock
|
||||
def f_empty():
|
||||
pass
|
||||
|
||||
@clock
|
||||
def f_args(a, b):
|
||||
return a*b
|
||||
|
||||
@clock
|
||||
def snooze(milis):
|
||||
time.sleep(milis/1000)
|
||||
|
||||
@clock
|
||||
def average(*args):
|
||||
return sum(args) / len(args)
|
||||
|
||||
@clock
|
||||
def factorial(n):
|
||||
return 1 if n < 2 else n*factorial(n-1)
|
||||
|
||||
@clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
import doctest
|
||||
doctest.testmod(optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
|
||||
50
decorators/currency.py
Normal file
50
decorators/currency.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# currency.py
|
||||
|
||||
"""
|
||||
>>> convert(1, 'BRL', 'USD')
|
||||
0.4591
|
||||
>>> convert(1, 'USD', 'BRL')
|
||||
2.1784
|
||||
>>> convert(1, 'EUR', 'USD')
|
||||
1.3482
|
||||
>>> convert(1, 'USD', 'EUR')
|
||||
0.7417
|
||||
>>> convert(1, 'EUR', 'BRL')
|
||||
2.9369
|
||||
>>> convert(1, 'BRL', 'EUR')
|
||||
0.3405
|
||||
|
||||
>>> from functools import partial
|
||||
>>> eur = partial(convert, cur_to='EUR')
|
||||
>>> eur(1, 'USD')
|
||||
0.7417
|
||||
>>> eur(1, 'BRL')
|
||||
0.3405
|
||||
>>> eur2brl = partial(convert, cur_from='EUR', cur_to='BRL')
|
||||
>>> eur2brl(100)
|
||||
293.6864
|
||||
>>> type(eur2brl)
|
||||
<class 'functools.partial'>
|
||||
"""
|
||||
|
||||
DEMO = """
|
||||
>>> eur2brl.func
|
||||
<function convert at 0x1010c5560>
|
||||
>>> eur2brl.args, eur2brl.keywords
|
||||
((), {'cur_from': 'EUR', 'cur_to': 'BRL'})
|
||||
"""
|
||||
|
||||
rates = {'BRL': 2.17836,
|
||||
'CAD': 1.03615,
|
||||
'CNY': 6.10562,
|
||||
'EUR': 0.74173,
|
||||
'GBP': 0.62814,
|
||||
'INR': 61.8685,
|
||||
'JPY': 98.6002,
|
||||
'USD': 1.0}
|
||||
|
||||
reference = rates['USD']
|
||||
|
||||
def convert(amount, cur_from, cur_to):
|
||||
ref_amount = reference / rates[cur_from] * amount
|
||||
return round(ref_amount * rates[cur_to], 4)
|
||||
10
decorators/fibo_demo.py
Normal file
10
decorators/fibo_demo.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from clockdeco import clock
|
||||
|
||||
@clock
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
if __name__=='__main__':
|
||||
print(fibonacci(6))
|
||||
13
decorators/fibo_demo_lru.py
Normal file
13
decorators/fibo_demo_lru.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import functools
|
||||
|
||||
from clockdeco import clock
|
||||
|
||||
@functools.lru_cache() # <1>
|
||||
@clock # <2>
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
if __name__=='__main__':
|
||||
print(fibonacci(6))
|
||||
60
decorators/fibonacci.py
Normal file
60
decorators/fibonacci.py
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
# source: http://oeis.org/A000045
|
||||
fibo_seq = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610,
|
||||
987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025,
|
||||
121393, 196418, 317811, 514229, 832040, 1346269, 2178309,
|
||||
3524578, 5702887, 9227465, 14930352, 24157817, 39088169]
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
def fibonacci(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci(n-2) + fibonacci(n-1)
|
||||
|
||||
@lru_cache()
|
||||
def fibonacci2(n):
|
||||
if n < 2:
|
||||
return n
|
||||
return fibonacci2(n-2) + fibonacci2(n-1)
|
||||
|
||||
def memoize(func):
|
||||
'''simplest memoizing decorator'''
|
||||
cache = {}
|
||||
def memoized(*args):
|
||||
if args not in cache:
|
||||
cache[args] = func(*args)
|
||||
return cache[args]
|
||||
return memoized
|
||||
|
||||
def test():
|
||||
for i, expected in enumerate(fibo_seq[:31]):
|
||||
print(i, expected)
|
||||
assert fibonacci(i) == expected
|
||||
|
||||
def chronograph():
|
||||
global fibonacci
|
||||
from time import time
|
||||
t0 = time()
|
||||
n = 32
|
||||
res = fibonacci(n)
|
||||
#res = [fibonacci(n) for n in range(30)]
|
||||
t1 = time()
|
||||
print(n, res, format(t1-t0, '0.6f'))
|
||||
|
||||
t0 = time()
|
||||
res = fibonacci2(n)
|
||||
#res = [fibonacci2(n) for n in range(30)]
|
||||
t1 = time()
|
||||
print(n, res, format(t1-t0, '0.6f'))
|
||||
|
||||
t0 = time()
|
||||
fibonacci = memoize(fibonacci)
|
||||
res = fibonacci(n)
|
||||
#res = [fibonacci2(n) for n in range(30)]
|
||||
t1 = time()
|
||||
print(n, res, format(t1-t0, '0.6f'))
|
||||
|
||||
if __name__=='__main__':
|
||||
#test()
|
||||
chronograph()
|
||||
49
decorators/generic.py
Normal file
49
decorators/generic.py
Normal file
@@ -0,0 +1,49 @@
|
||||
r"""
|
||||
htmlize(): generic function example
|
||||
|
||||
# BEGIN HTMLIZE_DEMO
|
||||
|
||||
>>> htmlize({1, 2, 3}) # <1>
|
||||
'<pre>{1, 2, 3}</pre>'
|
||||
>>> htmlize(abs)
|
||||
'<pre><built-in function abs></pre>'
|
||||
>>> htmlize('Heimlich & Co.\n- a game') # <2>
|
||||
'<p>Heimlich & Co.<br>\n- a game</p>'
|
||||
>>> htmlize(42) # <3>
|
||||
'<pre>42 (0x2a)</pre>'
|
||||
>>> print(htmlize(['alpha', 66, {3, 2, 1}])) # <4>
|
||||
<ul>
|
||||
<li><p>alpha</p></li>
|
||||
<li><pre>66 (0x42)</pre></li>
|
||||
<li><pre>{1, 2, 3}</pre></li>
|
||||
</ul>
|
||||
|
||||
# END HTMLIZE_DEMO
|
||||
"""
|
||||
|
||||
# BEGIN HTMLIZE
|
||||
|
||||
from functools import singledispatch
|
||||
import html
|
||||
|
||||
@singledispatch # <1>
|
||||
def htmlize(obj):
|
||||
content = html.escape(repr(obj))
|
||||
return '<pre>{}</pre>'.format(content)
|
||||
|
||||
@htmlize.register(str) # <2>
|
||||
def _(text): # <3>
|
||||
content = html.escape(text).replace('\n', '<br>\n')
|
||||
return '<p>{0}</p>'.format(content)
|
||||
|
||||
@htmlize.register(int) # <4>
|
||||
def _(n):
|
||||
return '<pre>{0} (0x{0:x})</pre>'.format(n)
|
||||
|
||||
@htmlize.register(list)
|
||||
def _(a_list):
|
||||
inner = '</li>\n<li>'.join(htmlize(item) for item in a_list)
|
||||
return '<ul>\n<li>' + inner + '</li>\n</ul>'
|
||||
|
||||
# END HTMLIZE
|
||||
|
||||
63
decorators/local_demo.py
Normal file
63
decorators/local_demo.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""
|
||||
>>> f1(3)
|
||||
>>> b = 8
|
||||
>>> f1(3)
|
||||
a = 3
|
||||
b = 8
|
||||
>>> f2(3)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
UnboundLocalError: local variable 'b' referenced before assignment
|
||||
>>> f3(3)
|
||||
a = 3
|
||||
b = 7
|
||||
b = 6
|
||||
>>> b = -5
|
||||
>>> ff = f4()
|
||||
>>> ff(3)
|
||||
a = 3
|
||||
b = 11
|
||||
b = 6
|
||||
>>> print('b =', b)
|
||||
b = -5
|
||||
"""
|
||||
|
||||
def f1(a):
|
||||
print('a =', a)
|
||||
print('b =', b)
|
||||
|
||||
def f2(a):
|
||||
print('a =', a)
|
||||
print('b =', b)
|
||||
b = a * 10
|
||||
print('b =', b)
|
||||
|
||||
def f3(a):
|
||||
global b
|
||||
print('a =', a)
|
||||
print('b =', b)
|
||||
b = a * 10
|
||||
print('b =', b)
|
||||
|
||||
def f3b(a):
|
||||
nonlocal b
|
||||
print('a =', a)
|
||||
print('b =', b)
|
||||
b = a * 10
|
||||
print('b =', b)
|
||||
|
||||
def f4():
|
||||
b = 11
|
||||
def f5(a):
|
||||
nonlocal b
|
||||
print('a =', a)
|
||||
print('b =', b)
|
||||
b = a * 2
|
||||
print('b =', b)
|
||||
return f5
|
||||
|
||||
import doctest
|
||||
doctest.testmod(optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE)
|
||||
|
||||
|
||||
|
||||
31
decorators/registration.py
Normal file
31
decorators/registration.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# BEGIN REGISTRATION
|
||||
|
||||
registry = [] # <1>
|
||||
|
||||
def register(func): # <2>
|
||||
print('running register(%s)' % func) # <3>
|
||||
registry.append(func) # <4>
|
||||
return func # <5>
|
||||
|
||||
@register # <6>
|
||||
def f1():
|
||||
print('running f1()')
|
||||
|
||||
@register
|
||||
def f2():
|
||||
print('running f2()')
|
||||
|
||||
def f3(): # <7>
|
||||
print('running f3()')
|
||||
|
||||
def main(): # <8>
|
||||
print('running main()')
|
||||
print('registry ->', registry)
|
||||
f1()
|
||||
f2()
|
||||
f3()
|
||||
|
||||
if __name__=='__main__':
|
||||
main() # <9>
|
||||
|
||||
# END REGISTRATION
|
||||
16
decorators/registration_abridged.py
Normal file
16
decorators/registration_abridged.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# BEGIN REGISTRATION_ABRIDGED
|
||||
registry = []
|
||||
|
||||
def register(func):
|
||||
print('running register(%s)' % func)
|
||||
registry.append(func)
|
||||
return func
|
||||
|
||||
@register
|
||||
def f1():
|
||||
print('running f1()')
|
||||
|
||||
print('running main()')
|
||||
print('registry ->', registry)
|
||||
f1()
|
||||
# END REGISTRATION_ABRIDGED
|
||||
29
decorators/registration_param.py
Normal file
29
decorators/registration_param.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# BEGIN REGISTRATION_PARAM
|
||||
|
||||
registry = set() # <1>
|
||||
|
||||
def register(active=True): # <2>
|
||||
def decorate(func): # <3>
|
||||
print('running register(active=%s)->decorate(%s)'
|
||||
% (active, func))
|
||||
if active: # <4>
|
||||
registry.add(func)
|
||||
else: # <5>
|
||||
if func in registry:
|
||||
registry.remove(func)
|
||||
|
||||
return func # <6>
|
||||
return decorate # <7>
|
||||
|
||||
@register(active=False) # <8>
|
||||
def f1():
|
||||
print('running f1()')
|
||||
|
||||
@register() # <9>
|
||||
def f2():
|
||||
print('running f2()')
|
||||
|
||||
def f3():
|
||||
print('running f3()')
|
||||
|
||||
# END REGISTRATION_PARAM
|
||||
27
decorators/stacked_demo.py
Normal file
27
decorators/stacked_demo.py
Normal file
@@ -0,0 +1,27 @@
|
||||
def d1(f):
|
||||
def wrapped():
|
||||
print('d1/wrapped')
|
||||
return f()
|
||||
return wrapped
|
||||
|
||||
|
||||
def d2(f):
|
||||
def wrapped():
|
||||
print('d2/wrapped')
|
||||
return f()
|
||||
return wrapped
|
||||
|
||||
|
||||
@d1
|
||||
@d2
|
||||
def f():
|
||||
print('f')
|
||||
|
||||
f()
|
||||
|
||||
def g():
|
||||
print('g')
|
||||
|
||||
g = d1(d2(g))
|
||||
|
||||
g()
|
||||
113
decorators/strategy_best4.py
Normal file
113
decorators/strategy_best4.py
Normal file
@@ -0,0 +1,113 @@
|
||||
# strategy_best4.py
|
||||
# Strategy pattern -- function-based implementation
|
||||
# selecting best promotion from list of functions
|
||||
# registered by a decorator
|
||||
|
||||
"""
|
||||
>>> joe = Customer('John Doe', 0)
|
||||
>>> ann = Customer('Ann Smith', 1100)
|
||||
>>> cart = [LineItem('banana', 4, .5),
|
||||
... LineItem('apple', 10, 1.5),
|
||||
... LineItem('watermellon', 5, 5.0)]
|
||||
>>> Order(joe, cart, fidelity)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
>>> Order(ann, cart, fidelity)
|
||||
<Order total: 42.00 due: 39.90>
|
||||
>>> banana_cart = [LineItem('banana', 30, .5),
|
||||
... LineItem('apple', 10, 1.5)]
|
||||
>>> Order(joe, banana_cart, bulk_item)
|
||||
<Order total: 30.00 due: 28.50>
|
||||
>>> long_order = [LineItem(str(item_code), 1, 1.0)
|
||||
... for item_code in range(10)]
|
||||
>>> Order(joe, long_order, large_order)
|
||||
<Order total: 10.00 due: 9.30>
|
||||
>>> Order(joe, cart, large_order)
|
||||
<Order total: 42.00 due: 42.00>
|
||||
|
||||
# BEGIN STRATEGY_BEST_TESTS
|
||||
|
||||
>>> Order(joe, long_order, best_promo)
|
||||
<Order total: 10.00 due: 9.30>
|
||||
>>> Order(joe, banana_cart, best_promo)
|
||||
<Order total: 30.00 due: 28.50>
|
||||
>>> Order(ann, cart, best_promo)
|
||||
<Order total: 42.00 due: 39.90>
|
||||
|
||||
# END STRATEGY_BEST_TESTS
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
Customer = namedtuple('Customer', 'name fidelity')
|
||||
|
||||
|
||||
class LineItem:
|
||||
|
||||
def __init__(self, product, quantity, price):
|
||||
self.product = product
|
||||
self.quantity = quantity
|
||||
self.price = price
|
||||
|
||||
def total(self):
|
||||
return self.price * self.quantity
|
||||
|
||||
|
||||
class Order: # the Context
|
||||
|
||||
def __init__(self, customer, cart, promotion=None):
|
||||
self.customer = customer
|
||||
self.cart = list(cart)
|
||||
self.promotion = promotion
|
||||
|
||||
def total(self):
|
||||
if not hasattr(self, '__total'):
|
||||
self.__total = sum(item.total() for item in self.cart)
|
||||
return self.__total
|
||||
|
||||
def due(self):
|
||||
if self.promotion is None:
|
||||
discount = 0
|
||||
else:
|
||||
discount = self.promotion(self)
|
||||
return self.total() - discount
|
||||
|
||||
def __repr__(self):
|
||||
fmt = '<Order total: {:.2f} due: {:.2f}>'
|
||||
return fmt.format(self.total(), self.due())
|
||||
|
||||
# BEGIN STRATEGY_BEST4
|
||||
|
||||
promos = [] # <1>
|
||||
|
||||
def promotion(promo_func): # <2>
|
||||
promos.append(promo_func)
|
||||
return promo_func
|
||||
|
||||
@promotion # <3>
|
||||
def fidelity(order):
|
||||
"""5% discount for customers with 1000 or more fidelity points"""
|
||||
return order.total() * .05 if order.customer.fidelity >= 1000 else 0
|
||||
|
||||
@promotion
|
||||
def bulk_item(order):
|
||||
"""10% discount for each LineItem with 20 or more units"""
|
||||
discount = 0
|
||||
for item in order.cart:
|
||||
if item.quantity >= 20:
|
||||
discount += item.total() * .1
|
||||
return discount
|
||||
|
||||
@promotion
|
||||
def large_order(order):
|
||||
"""7% discount for orders with 10 or more distinct items"""
|
||||
distinct_items = {item.product for item in order.cart}
|
||||
if len(distinct_items) >= 10:
|
||||
return order.total() * .07
|
||||
return 0
|
||||
|
||||
def best_promo(order): # <4>
|
||||
"""Select best discount available
|
||||
"""
|
||||
return max(promo(order) for promo in promos)
|
||||
|
||||
# END STRATEGY_BEST4
|
||||
Reference in New Issue
Block a user