Skip to content

Commit b6eb3ef

Browse files
committed
ch06
1 parent ef37ce0 commit b6eb3ef

32 files changed

+1063
-0
lines changed

ch06/decorators/decorators.factory.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# decorators/decorators.factory.py
2+
from functools import wraps
3+
4+
def max_result(threshold):
5+
def decorator(func):
6+
@wraps(func)
7+
def wrapper(*args, **kwargs):
8+
result = func(*args, **kwargs)
9+
if result > threshold:
10+
print(
11+
f'Result is too big ({result}). '
12+
f'Max allowed is {threshold}.'
13+
)
14+
return result
15+
return wrapper
16+
return decorator
17+
18+
@max_result(75)
19+
def cube(n):
20+
return n ** 3
21+
22+
@max_result(100)
23+
def square(n):
24+
return n ** 2
25+
26+
@max_result(1000)
27+
def multiply(a, b):
28+
return a * b
29+
30+
print(cube(5))
31+
32+
33+
"""
34+
$ python decorators.factory.py
35+
Result is too big (125). Max allowed is 75.
36+
125
37+
"""

ch06/decorators/syntax.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# decorators/syntax.py
2+
# This is not a valid Python module - Don't run it.
3+
4+
# ONE DECORATOR
5+
def func(arg1, arg2, ...):
6+
pass
7+
8+
func = decorator(func)
9+
10+
# is equivalent to the following:
11+
12+
@decorator
13+
def func(arg1, arg2, ...):
14+
pass
15+
16+
17+
# TWO DECORATORS
18+
def func(arg1, arg2, ...):
19+
pass
20+
21+
func = deco1(deco2(func))
22+
23+
# is equivalent to the following:
24+
25+
@deco1
26+
@deco2
27+
def func(arg1, arg2, ...):
28+
pass
29+
30+
# DECORATOR WITH ARGUMENTS
31+
def func(arg1, arg2, ...):
32+
pass
33+
34+
func = decoarg(arg_a, arg_b)(func)
35+
36+
# is equivalent to the following:
37+
38+
@decoarg(arg_a, arg_b)
39+
def func(arg1, arg2, ...):
40+
pass
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# decorators/time.measure.arguments.py
2+
from time import sleep, time
3+
4+
5+
def f(sleep_time=0.1):
6+
sleep(sleep_time)
7+
8+
def measure(func, *args, **kwargs):
9+
t = time()
10+
func(*args, **kwargs)
11+
print(func.__name__, 'took:', time() - t)
12+
13+
measure(f, sleep_time=0.3) # f took: 0.30056095123291016
14+
measure(f, 0.2) # f took: 0.2033553123474121

ch06/decorators/time.measure.deco1.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# decorators/time.measure.deco1.py
2+
from time import sleep, time
3+
4+
def f(sleep_time=0.1):
5+
sleep(sleep_time)
6+
7+
def measure(func):
8+
def wrapper(*args, **kwargs):
9+
t = time()
10+
func(*args, **kwargs)
11+
print(func.__name__, 'took:', time() - t)
12+
return wrapper
13+
14+
f = measure(f) # decoration point
15+
16+
f(0.2) # f took: 0.20372915267944336
17+
f(sleep_time=0.3) # f took: 0.30455899238586426
18+
print(f.__name__) # wrapper <- ouch!

ch06/decorators/time.measure.deco2.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# decorators/time.measure.deco2.py
2+
from time import sleep, time
3+
from functools import wraps
4+
5+
6+
def measure(func):
7+
@wraps(func)
8+
def wrapper(*args, **kwargs):
9+
t = time()
10+
func(*args, **kwargs)
11+
print(func.__name__, 'took:', time() - t)
12+
return wrapper
13+
14+
15+
@measure
16+
def f(sleep_time=0.1):
17+
"""I'm a cat. I love to sleep! """
18+
sleep(sleep_time)
19+
20+
21+
f(sleep_time=0.3) # f took: 0.3010902404785156
22+
print(f.__name__, ':', f.__doc__) # f : I'm a cat. I love to sleep!

ch06/decorators/time.measure.dry.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# decorators/time.measure.dry.py
2+
from time import sleep, time
3+
4+
5+
def f():
6+
sleep(.3)
7+
8+
def g():
9+
sleep(.5)
10+
11+
def measure(func):
12+
t = time()
13+
func()
14+
print(func.__name__, 'took:', time() - t)
15+
16+
measure(f) # f took: 0.30434322357177734
17+
measure(g) # g took: 0.5048270225524902

ch06/decorators/time.measure.start.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# decorators/time.measure.start.py
2+
from time import sleep, time
3+
4+
5+
def f():
6+
sleep(.3)
7+
8+
def g():
9+
sleep(.5)
10+
11+
12+
t = time()
13+
f()
14+
print('f took:', time() - t) # f took: 0.3001396656036377
15+
16+
t = time()
17+
g()
18+
print('g took:', time() - t) # g took: 0.5039339065551758

ch06/decorators/two.decorators.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# decorators/two.decorators.py
2+
from time import time
3+
from functools import wraps
4+
5+
def measure(func):
6+
@wraps(func)
7+
def wrapper(*args, **kwargs):
8+
t = time()
9+
result = func(*args, **kwargs)
10+
print(func.__name__, 'took:', time() - t)
11+
return result
12+
return wrapper
13+
14+
def max_result(func):
15+
@wraps(func)
16+
def wrapper(*args, **kwargs):
17+
result = func(*args, **kwargs)
18+
if result > 100:
19+
print(
20+
f'Result is too big ({result}). '
21+
'Max allowed is 100.'
22+
)
23+
return result
24+
return wrapper
25+
26+
@measure
27+
@max_result
28+
def cube(n):
29+
return n ** 3
30+
31+
print(cube(2))
32+
print(cube(5))
33+
34+
35+
"""
36+
$ python two.decorators.py
37+
cube took: 3.0994415283203125e-06
38+
8
39+
Result is too big (125). Max allowed is 100.
40+
cube took: 5.9604644775390625e-06
41+
125
42+
"""

ch06/iterators/iterator.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# iterators/iterator.py
2+
class OddEven:
3+
4+
def __init__(self, data):
5+
self._data = data
6+
self.indexes = (list(range(0, len(data), 2)) +
7+
list(range(1, len(data), 2)))
8+
9+
def __iter__(self):
10+
return self
11+
12+
def __next__(self):
13+
if self.indexes:
14+
return self._data[self.indexes.pop(0)]
15+
raise StopIteration
16+
17+
oddeven = OddEven('ThIsIsCoOl!')
18+
print(''.join(c for c in oddeven)) # TIICO!hssol
19+
20+
oddeven = OddEven('CiAo') # or manually...
21+
it = iter(oddeven) # this calls oddeven.__iter__ internally
22+
print(next(it)) # C
23+
print(next(it)) # A
24+
print(next(it)) # i
25+
print(next(it)) # o
26+
27+
28+
# make sure it works correctly with edge cases
29+
oddeven = OddEven('')
30+
print(' '.join(c for c in oddeven))
31+
32+
oddeven = OddEven('A')
33+
print(' '.join(c for c in oddeven))
34+
35+
oddeven = OddEven('Ab')
36+
print(' '.join(c for c in oddeven))
37+
38+
oddeven = OddEven('AbC')
39+
print(' '.join(c for c in oddeven))
40+
41+
42+
"""
43+
$ python iterators/iterator.py
44+
TIICO!hssol
45+
C
46+
A
47+
i
48+
o
49+
50+
A
51+
A b
52+
A C b
53+
"""

ch06/oop/cached.property.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# oop/cached.property.py
2+
from functools import cached_property
3+
4+
5+
class Client:
6+
def __init__(self):
7+
print("Setting up the client...")
8+
9+
def query(self, **kwargs):
10+
print(f"Performing a query: {kwargs}")
11+
12+
13+
class Manager:
14+
@property
15+
def client(self):
16+
return Client()
17+
18+
def perform_query(self, **kwargs):
19+
return self.client.query(**kwargs)
20+
21+
22+
class ManualCacheManager:
23+
@property
24+
def client(self):
25+
if not hasattr(self, '_client'):
26+
self._client = Client()
27+
return self._client
28+
29+
def perform_query(self, **kwargs):
30+
return self.client.query(**kwargs)
31+
32+
33+
class CachedPropertyManager:
34+
@cached_property
35+
def client(self):
36+
return Client()
37+
38+
def perform_query(self, **kwargs):
39+
return self.client.query(**kwargs)
40+
41+
42+
manager = CachedPropertyManager()
43+
manager.perform_query(object_id=42)
44+
manager.perform_query(name_ilike='%Python%')
45+
46+
del manager.client # This causes a new Client on next call
47+
manager.perform_query(age_gte=18)
48+
49+
50+
"""
51+
$ python cached.property.py
52+
Setting up the client... # New Client
53+
Performing a query: {'object_id': 42} # first query
54+
Performing a query: {'name_ilike': '%Python%'} # second query
55+
Setting up the client... # Another Client
56+
Performing a query: {'age_gte': 18} # Third query
57+
"""

0 commit comments

Comments
 (0)