Skip to content

Commit b3e8fe7

Browse files
committed
Add source code examples
1 parent 016eab5 commit b3e8fe7

File tree

96 files changed

+8857
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+8857
-0
lines changed

source-code/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Source code
2+
3+
This source code illustrates concepts in the training and
4+
was used to develop it.
5+
6+
7+
## What is it?
8+
9+
1. `context-manager`: illustrates how to write your own context managers.
10+
1. `coroutines`: illustrates how to write coroutines in Python.
11+
1. `design-patterns`: illustrates some common design patterns in Python.
12+
1. `functional-programming`: illustrates some concepts of functional
13+
programming in Python.
14+
1. `object-orientation`: illustrates some concepts of object-oriented
15+
programming in Python.
16+
1. `operators-functools`: illustrates some applications of the `operator`
17+
and `functools` modules in Python's standard library.
18+
1. `typing`: illustrates how to use type annotation in Python, and
19+
demonstrates `mypy`.
20+
1. `unit-testing`: illustrates writing unit tests with `unittest` and
21+
`pytest`.

source-code/context-manager/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Context manager
2+
===============
3+
4+
A context manager can be used to initialize and finalize resources. Once
5+
defined, they can be used with Python's `with` construct.
6+
7+
What is it?
8+
-----------
9+
`context.py`: illustrates two ways to define a context manager,
10+
* as a class, providing hooks on instantiation, entering, and exiting
11+
the context.
12+
* as function decorator, where code to be executed for initialization,
13+
entering, and exiting sandwiches a `yield` statement that returns the
14+
value.
15+
16+
Note
17+
----
18+
The exception is raised on purpose to illustrate exception handling by
19+
a context manager.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python
2+
3+
from contextlib import contextmanager
4+
import sys
5+
6+
7+
class ContextTest(object):
8+
9+
def __init__(self, context_nr):
10+
self._context_nr = context_nr
11+
print('created with {0}'.format(self._context_nr))
12+
13+
def __enter__(self):
14+
print('entering {0}'.format(self._context_nr))
15+
return self
16+
17+
def __exit__(self, exception_type, exception_value, backtrace):
18+
print('exiting {0}'.format(self._context_nr))
19+
if exception_type:
20+
print('exception in context {0}:'.format(self._context_nr))
21+
print('\t', exception_type, exception_value, backtrace)
22+
return
23+
else:
24+
print('no exception in context {0}'.format(self._context_nr))
25+
26+
27+
@contextmanager
28+
def label(name):
29+
print('entering label({0})'.format(name))
30+
yield name
31+
print('exiting label({0})'. format(name))
32+
33+
34+
def main():
35+
with ContextTest(1) as c1, ContextTest(2) as c2:
36+
print('in context {0}'.format(c1._context_nr))
37+
print('in context {0}'.format(c2._context_nr))
38+
with label('foo') as foo, label('bar') as bar:
39+
print(foo, bar)
40+
with ContextTest(1) as c1, ContextTest(2) as c2:
41+
print('in context {0}'.format(c1._context_nr))
42+
raise Exception()
43+
print('in context {0}'.format(c2._context_nr))
44+
return 0
45+
46+
if __name__ == '__main__':
47+
status = main()
48+
sys.exit(status)

source-code/coroutines/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Coroutines
2+
==========
3+
4+
Coroutines provide a powerful programming paradigm for functions that
5+
preserve state between invocations.
6+
7+
What is it?
8+
-----------
9+
1. `coroutine.py`: implements a coroutine `my_printer` that can can be
10+
"created" by invocating the function, "started" using the `next()`
11+
method, "invoked" using the `send()` method, and terminated using
12+
the `close()` method.
13+
1. `longest_run.py`: stateful streaming parser implemented using a
14+
coroutine. It keeps track of the longest run of characters in
15+
a string that is presented one batch at the time.
16+
1. `stats.py`: coroutine implementation for collecting statistics (mean,
17+
standard deviation).
18+
1. `data.txt`: data file to compute statistical measures from.

source-code/coroutines/coroutines.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env python
2+
3+
4+
def my_printer():
5+
try:
6+
counter = 0
7+
while True:
8+
buffer = (yield)
9+
counter += 1
10+
print('{0:03d}: {1}'.format(counter, buffer))
11+
except GeneratorExit:
12+
pass
13+
14+
15+
def main():
16+
coroutine = my_printer()
17+
next(coroutine)
18+
for i in range(26):
19+
str = chr(ord('A') + i)
20+
coroutine.send(str)
21+
coroutine.close()
22+
23+
if __name__ == '__main__':
24+
main()

source-code/coroutines/data.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
alpha, beta, gamma
2+
1.0, 17.3, -3.3
3+
2.0, 14.5, -2.9
4+
3.0, 15.7, -4.9
5+
4.0, 14.3, -3.4
6+

source-code/coroutines/longest_run.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env python
2+
3+
from collections import defaultdict
4+
5+
6+
def longest_run():
7+
runs = defaultdict(lambda: 0)
8+
buffer = None
9+
while True:
10+
data = yield runs
11+
if data:
12+
if not buffer:
13+
prev = data.pop(0)
14+
buffer = [prev]
15+
run_length = 1
16+
else:
17+
prev = buffer[-1]
18+
if prev != data[0]:
19+
run_length = len(buffer)
20+
if run_length > runs[prev]:
21+
runs[prev] = run_length
22+
prev = data.pop(0)
23+
buffer = [prev]
24+
run_length = 1
25+
else:
26+
buffer.append(prev)
27+
while data:
28+
current = data.pop(0)
29+
if current == prev:
30+
run_length += 1
31+
buffer.append(current)
32+
else:
33+
if run_length > runs[prev]:
34+
runs[prev] = run_length
35+
prev = current
36+
buffer = [prev]
37+
run_length = 1
38+
return runs
39+
40+
41+
def print_run_lengths(runs, prefix=''):
42+
for char, run_length in runs.items():
43+
print(f'{prefix}{char}: {run_length}')
44+
45+
if __name__ == '__main__':
46+
data_stream = [
47+
'aabbbba',
48+
'aaaabb',
49+
'bbbbbaa',
50+
]
51+
longest_runner = longest_run()
52+
next(longest_runner)
53+
for block_nr, data in enumerate(data_stream):
54+
print(data)
55+
runs = longest_runner.send(list(data))
56+
print(f' result for block {block_nr + 1}')
57+
print_run_lengths(runs, ' ')
58+
longest_runner.close()

source-code/coroutines/stats.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python
2+
3+
from collections import namedtuple
4+
from math import sqrt
5+
import sys
6+
7+
Result = namedtuple('Result', ['mean', 'stddev'])
8+
9+
10+
def stats():
11+
sum = 0.0
12+
sum2 = 0.0
13+
count = 0
14+
while True:
15+
number = yield
16+
if number is None:
17+
break
18+
sum += number
19+
sum2 += number**2
20+
count += 1
21+
return Result(sum/count, sqrt((sum2 - sum**2/count)/(count - 1)))
22+
23+
24+
def process_line(line, mode=float):
25+
line = line.strip()
26+
if not line:
27+
return None
28+
items = [item.strip() for item in line.split(',')]
29+
if mode == float:
30+
return [float(item) for item in items]
31+
else:
32+
return items
33+
34+
if __name__ == '__main__':
35+
line = sys.stdin.readline()
36+
names = process_line(line, mode='text')
37+
averagers = [stats() for name in names]
38+
for averager in averagers:
39+
next(averager)
40+
for line in sys.stdin:
41+
data = process_line(line)
42+
if not data:
43+
continue
44+
for number, averager in zip(data, averagers):
45+
averager.send(number)
46+
for name, averager in zip(names, averagers):
47+
try:
48+
averager.send(None)
49+
except StopIteration as exception:
50+
result = exception.value
51+
print('{0}: {1:.3f}, {2:.3f}'.format(name,
52+
result.mean,
53+
result.stddev))

source-code/design-patters/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Design patterns
2+
3+
Code to illustrate some design patterns in Python.
4+
5+
## What is it?
6+
7+
1. `decorator_design_pattern.ipynb`: notebook that illustrate how decorators
8+
can be used to change the behaviour of objects.

source-code/design-patters/decorator_design_pattern.ipynb

Lines changed: 519 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)