Skip to content

Commit 1bf1645

Browse files
committed
Add module functools
1 parent 29bbfc2 commit 1bf1645

12 files changed

Lines changed: 370 additions & 0 deletions
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import functools
2+
3+
4+
class MyObject:
5+
def __init__(self, val):
6+
self.val = val
7+
8+
def __str__(self):
9+
return 'MyObject({})'.format(self.val)
10+
11+
12+
def compare_obj(a, b):
13+
"""Old-style comparison function."""
14+
print('comparing {} and {}'.format(a, b))
15+
if a.val < b.val:
16+
return -1
17+
elif a.val > b.val:
18+
return 1
19+
return 0
20+
21+
22+
# Make a key function using cmp_to_key()
23+
get_key = functools.cmp_to_key(compare_obj)
24+
25+
26+
def get_key_wrapper(o):
27+
"""Wrapper function for get_key to allow for print statements."""
28+
new_key = get_key(o)
29+
print('key_wrapper({}) -> {!r}'.format(o, new_key))
30+
return new_key
31+
32+
33+
objs = [MyObject(x) for x in range(5, 0, -1)]
34+
for o in sorted(objs, key=get_key_wrapper):
35+
print(o)
36+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import functools
2+
3+
4+
@functools.lru_cache()
5+
def expensive(a, b):
6+
print('expensive({}, {})'.format(a, b))
7+
return a * b
8+
9+
10+
MAX = 2
11+
12+
print('First set of calls: ')
13+
for i in range(MAX):
14+
for j in range(MAX):
15+
expensive(i, j)
16+
print(expensive.cache_info())
17+
18+
print('\nSecond set of calls')
19+
for i in range(MAX + 1):
20+
for j in range(MAX + 1):
21+
expensive(i, j)
22+
print(expensive.cache_info())
23+
24+
print('\nClearing cache: ')
25+
expensive.cache_clear()
26+
print(expensive.cache_info())
27+
28+
print('\nThird set of calls: ')
29+
for i in range(MAX):
30+
for j in range(MAX):
31+
expensive(i, j)
32+
print(expensive.cache_info())
33+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import functools
2+
3+
4+
@functools.lru_cache(maxsize=2)
5+
def expensive(a, b):
6+
print('called expensive({}, {})'.format(a, b))
7+
return a * b
8+
9+
10+
def make_call(a, b):
11+
print('({}, {})'.format(a, b), end=' ')
12+
pre_hits = expensive.cache_info().hits
13+
expensive(a, b)
14+
post_hits = expensive.cache_info().hits
15+
if post_hits > pre_hits:
16+
print('cache hit')
17+
18+
19+
make_call(1, 2)
20+
try:
21+
make_call([1], 2)
22+
except TypeError as err:
23+
print('ERROR: {}'.format(err))
24+
25+
try:
26+
make_call(1, {'2': 'two'})
27+
except TypeError as err:
28+
print('ERROR: {}'.format(err))
29+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import functools
2+
3+
4+
@functools.lru_cache(maxsize=2)
5+
def expensive(a, b):
6+
print('called expensive({}, {})'.format(a, b))
7+
return a * b
8+
9+
10+
def make_call(a, b):
11+
print('({}, {})'.format(a, b), end=' ')
12+
pre_hits = expensive.cache_info().hits
13+
expensive(a, b)
14+
post_hits = expensive.cache_info().hits
15+
if post_hits > pre_hits:
16+
print('cache hit')
17+
18+
19+
print('Establish the cache')
20+
make_call(1, 2)
21+
make_call(2, 3)
22+
23+
print('\nUse cache items')
24+
make_call(1, 2)
25+
make_call(2, 3)
26+
27+
print('\nCompute a new value, triggering cache expiration')
28+
make_call(3, 4)
29+
30+
print('\nCache still contains one old item')
31+
make_call(2, 3)
32+
33+
print('\nOldest item needs to be recomputed')
34+
make_call(1, 2)
35+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import functools
2+
3+
4+
def standalone(self, a=1, b=2):
5+
"""Standalone function"""
6+
print('called standalone with: ', (self, a, b))
7+
if self is not None:
8+
print('self.attr = ', self.attr)
9+
10+
11+
class MyClass:
12+
"""Demonstration class for functools"""
13+
def __init__(self):
14+
self.attr = 'instance attribute'
15+
16+
method1 = functools.partialmethod(standalone)
17+
method2 = functools.partial(standalone)
18+
19+
20+
o = MyClass()
21+
print('standalone')
22+
standalone(None)
23+
print()
24+
25+
print('method1 as partialmethod')
26+
o.method1()
27+
print()
28+
29+
print('method2 as partial')
30+
try:
31+
o.method2()
32+
except TypeError as err:
33+
print('ERROR: {}'.format(err))
34+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import functools
2+
3+
4+
def do_reduce(a, b):
5+
print('do_reduce({}, {})'.format(a, b))
6+
return a + b
7+
8+
9+
data = range(1, 5)
10+
print(data)
11+
result = functools.reduce(do_reduce, data)
12+
print('result: {}'.format(result))
13+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import functools
2+
3+
4+
def do_reduce(a, b):
5+
print('do_reduce({}, {})'.format(a, b))
6+
return a + b
7+
8+
9+
data = range(1, 5)
10+
print(data)
11+
result = functools.reduce(do_reduce, data, 99)
12+
print('result: {}'.format(result))
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import functools
2+
3+
4+
def do_reduce(a, b):
5+
print('do_reduce({}, {})'.format(a, b))
6+
return a + b
7+
8+
9+
print('Single item in sequence: ', functools.reduce(do_reduce, [1]))
10+
print('Single item in sequence with initializer: ', functools.reduce(do_reduce, [1], 99))
11+
print('Empty sequence with initializer: ', functools.reduce(do_reduce, [], 99))
12+
try:
13+
print('Empty sequence: ', functools.reduce(do_reduce, []))
14+
except TypeError as err:
15+
print('ERROR: {}'.format(err))
16+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import functools
2+
3+
4+
@functools.singledispatch
5+
def myfunc(arg):
6+
print('default myfunc({!r})'.format(arg))
7+
8+
9+
@myfunc.register(int)
10+
def myfunc_int(arg):
11+
print('myfunc_int({})'.format(arg))
12+
13+
14+
@myfunc.register(list)
15+
def myfunc_list(arg):
16+
print('myfunc_list()')
17+
for item in arg:
18+
print(' {}'.format(item))
19+
20+
21+
myfunc('string argument')
22+
myfunc(1)
23+
myfunc(2.3)
24+
myfunc(['a', 'b', 'c'])
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import functools
2+
3+
4+
class A:
5+
pass
6+
7+
8+
class B(A):
9+
pass
10+
11+
12+
class C(A):
13+
pass
14+
15+
16+
class D(B):
17+
pass
18+
19+
20+
class E(C, D):
21+
pass
22+
23+
24+
@functools.singledispatch
25+
def myfunc(arg):
26+
print('default myfunc({})'.format(arg.__class__.__name__))
27+
28+
29+
@myfunc.register(A)
30+
def myfunc_A(arg):
31+
print('myfunc_A({})'.format(arg.__class__.__name__))
32+
33+
34+
@myfunc.register(B)
35+
def myfunc_B(arg):
36+
print('myfunc_B({})'.format(arg.__class__.__name__))
37+
38+
39+
@myfunc.register(C)
40+
def myfunc_C(arg):
41+
print('myfunc_C({})'.format(arg.__class__.__name__))
42+
43+
44+
myfunc(A())
45+
myfunc(B())
46+
myfunc(C())
47+
myfunc(D())
48+
myfunc(E())
49+

0 commit comments

Comments
 (0)