Skip to content

Commit 57097ca

Browse files
committed
Add clean example using a factory function
1 parent 6aca35f commit 57097ca

File tree

2 files changed

+67
-23
lines changed

2 files changed

+67
-23
lines changed

source-code/typing/README.md

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,40 @@
1-
# Typing
2-
Python 3.5 introducd optional type annotation for functions, and that
3-
functionality was extended in Python 3.6.
1+
# Typing Python 3.5 introducd optional type annotation for functions, and
2+
that functionality was extended in Python 3.6.
43

5-
The `mypy` static type checker can use this annotation to detect type
6-
errors.
4+
The `mypy` static type checker can use this annotation to detect type errors.
75

86
Type checking can be done using [mypy](http://mypy-lang.org/index.html).
97

108
## What is it?
119
1. `mypy.ini`: mypy configuration file.
1210
1. `correct.py`: code that has type annotations, and no type errors.
13-
1. `incorrect_01.py`: code that has type annotations, and passes a string
14-
to a function that expects an `int`.
11+
1. `incorrect_01.py`: code that has type annotations, and passes a string to
12+
a function that expects an `int`.
1513
1. `incorrect_02.py`: code that has type annotations, and the result of a
16-
function that returns an `int` is assigned to a `str` variable.
14+
function that returns an `int` is assigned to a `str` variable.
1715
1. `incorrect_03.py`: code that has type annotations, and the result of a
18-
function that returns an `int`, assigns it to a variable that is
19-
later used as a `str`.
20-
1. `dict_correct.py`: code that counts the words in a text read from
21-
standard input.
16+
function that returns an `int`, assigns it to a variable that is later
17+
used as a `str`.
18+
1. `dict_correct.py`: code that counts the words in a text read from standard
19+
input.
2220
1. `dict_incorrect.py`: code that counts the words in a text read from
23-
standard input. The counts are subsequently normalized to `float`,
24-
which is a type error.
25-
1. `people_incorrect.py`: code that defines a `People` class, stores some
26-
in a list with mistakes.
21+
standard input. The counts are subsequently normalized to `float`, which
22+
is a type error.
23+
1. `people_incorrect.py`: code that defines a `People` class, stores some in
24+
a list with mistakes.
2725
1. `duck_typing.py`: example code illustrating duck typing.
2826
1. `duck_typing_incorrect.py`: example code illustrating duck typing, but
2927
with an error.
30-
1. `typed_duck_typing.py`: example code illustrating duck typing
31-
using type hints.
28+
1. `typed_duck_typing.py`: example code illustrating duck typing using type
29+
hints.
30+
1. `typed_duck_typing_clean.py`: example code illustrating duck typing using
31+
type hints with a factory function.
3232
1. `typed_duck_typing_incorrect.py`: example code illustrating duck typing
3333
using type hints with an error.
34-
1. `typed_duck_typing_false_positive.py`: example code illustrating
35-
duck typing using type hints for which mypy 0.910 generates a
36-
false positive.
34+
1. `typed_duck_typing_false_positive.py`: example code illustrating duck
35+
typing using type hints for which mypy 0.910 generates a false positive.
3736
1. `numpy_typing.py`: illustration of a script using both numpy and
3837
matplotlib with type hints.
39-
1. `classes.py`: illustration of using type hints with a user-defined
40-
class.
38+
1. `classes.py`: illustration of using type hints with a user-defined class.
4139
1. `classes_incorrect.py`: illustration of using type hints with a
4240
user-defined class with errors.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
import argparse
3+
from typing import Protocol
4+
5+
6+
class SoundMaker(Protocol):
7+
8+
def make_sound(self) -> None:
9+
pass
10+
11+
12+
class Duck:
13+
14+
def make_sound(self) -> None:
15+
print('quack')
16+
17+
18+
class AlarmClock:
19+
20+
def make_sound(self) -> None:
21+
print('ring-ring')
22+
23+
24+
def sound_maker_factory(sound_type: str) -> SoundMaker:
25+
if sound_type == 'duck':
26+
return Duck()
27+
elif sound_type == 'alarm':
28+
return AlarmClock()
29+
else:
30+
raise ValueError(f'unknown sound type: {sound_type}')
31+
32+
33+
def sound_repeater(sound_maker: SoundMaker, nr_repeats: int) -> None:
34+
for _ in range(nr_repeats):
35+
sound_maker.make_sound()
36+
37+
38+
if __name__ == '__main__':
39+
arg_parser = argparse.ArgumentParser(description='sound maker')
40+
arg_parser.add_argument('--type', choices=['duck', 'alarm'],
41+
help='sound source')
42+
arg_parser.add_argument('--n', type=int, default=1,
43+
help='number of sounds to make')
44+
options = arg_parser.parse_args()
45+
sound_maker: SoundMaker = sound_maker_factory(options.type)
46+
sound_repeater(sound_maker, options.n)

0 commit comments

Comments
 (0)