Skip to content

Commit bf4a2be

Browse files
committed
ch08, 09, 10: example files
1 parent 42861b6 commit bf4a2be

File tree

111 files changed

+4707
-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.

111 files changed

+4707
-0
lines changed

08-def-type-hints/README.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
== Type Hints in Function Definitions

08-def-type-hints/RPN_calc/calc.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env python3
2+
3+
import sys
4+
from array import array
5+
from typing import Mapping, MutableSequence, Callable, Iterable, Sequence, Union, Any
6+
7+
8+
OPERATORS: Mapping[str, Callable[[float, float], float]] = {
9+
'+': lambda a, b: a + b,
10+
'-': lambda a, b: a - b,
11+
'*': lambda a, b: a * b,
12+
'/': lambda a, b: a / b,
13+
'^': lambda a, b: a ** b,
14+
}
15+
16+
17+
Stack = MutableSequence[float]
18+
19+
20+
def parse_token(token: str) -> Union[str, float]:
21+
try:
22+
return float(token)
23+
except ValueError:
24+
return token
25+
26+
27+
def evaluate(tokens: Iterable[str], stack: Stack) -> None:
28+
for token in tokens:
29+
atom = parse_token(token)
30+
if isinstance(atom, float):
31+
stack.append(atom)
32+
else: # not float, must be operator
33+
op = OPERATORS[atom]
34+
x, y = stack.pop(), stack.pop()
35+
result = op(y, x)
36+
stack.append(result)
37+
38+
39+
def display(s: Stack) -> str:
40+
items = (repr(n) for n in s)
41+
return ' │ '.join(items) + ' →'
42+
43+
44+
def repl(input_fn: Callable[[Any], str] = input) -> None:
45+
"""Read-Eval-Print-Loop"""
46+
47+
print('Use CTRL+C to quit.', file=sys.stderr)
48+
stack: Stack = array('d')
49+
50+
while True:
51+
try:
52+
line = input_fn('> ') # Read
53+
except (EOFError, KeyboardInterrupt):
54+
break
55+
try:
56+
evaluate(line.split(), stack) # Eval
57+
except IndexError:
58+
print('*** Not enough arguments.', file=sys.stderr)
59+
except KeyError as exc:
60+
print('*** Unknown operator:', exc.args[0], file=sys.stderr)
61+
print(display(stack)) # Print
62+
63+
print()
64+
65+
66+
if __name__ == '__main__':
67+
repl()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from pytest import mark, approx # type: ignore
2+
3+
from dialogue import Dialogue # type: ignore
4+
5+
from calc import evaluate, repl, display, Stack
6+
7+
TOLERANCE = .0001
8+
9+
@mark.parametrize("source, want", [
10+
('2', 2),
11+
('2 3 +', 5),
12+
('5 3 -', 2),
13+
('3 5 * 2 +', 17),
14+
('2 3 4 5 * * *', 120),
15+
('1.1 1.1 1.1 + +', approx(3.3, TOLERANCE)),
16+
('100 32 - 5 * 9 /', approx(37.78, TOLERANCE)),
17+
])
18+
def test_evaluate(source, want) -> None:
19+
stack: Stack = []
20+
evaluate(source.split(), stack)
21+
assert want == stack[-1]
22+
23+
24+
@mark.parametrize("value, want", [
25+
([], ' →'),
26+
([3.], '3.0 →'),
27+
([3., 4., 5.], '3.0 │ 4.0 │ 5.0 →'),
28+
])
29+
def test_display(value, want) -> None:
30+
assert want == display(value)
31+
32+
33+
@mark.parametrize("session", [
34+
"""
35+
> 3
36+
3.0 →
37+
""",
38+
"""
39+
> 3 5 6
40+
3.0 │ 5.0 │ 6.0 →
41+
> *
42+
3.0 │ 30.0 →
43+
> -
44+
-27.0 →
45+
""",
46+
])
47+
def test_repl(capsys, session) -> None:
48+
dlg = Dialogue(session)
49+
repl(dlg.fake_input)
50+
captured = capsys.readouterr()
51+
assert dlg.session.strip() == captured.out.strip()

08-def-type-hints/arg_lab.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import typing
2+
from typing import Optional
3+
4+
5+
def f(a: str, *b: int, **c: float) -> None:
6+
if typing.TYPE_CHECKING:
7+
# reveal_type(b)
8+
reveal_type(c)
9+
print(a, b, c)
10+
11+
12+
def g(__a: int) -> None:
13+
print(__a)
14+
15+
16+
def h(a: int, /) -> None:
17+
print(a)
18+
19+
20+
def tag(
21+
name: str,
22+
/,
23+
*content: str,
24+
class_: Optional[str] = None,
25+
foo: Optional[str] = None,
26+
**attrs: str,
27+
) -> str:
28+
return repr((name, content, class_, attrs))
29+
30+
31+
f(a='1')
32+
f('1', 2, 3, x=4, y=5)
33+
g(__a=1)
34+
# h(a=1)
35+
print(tag('li', 'first', 'second', id='#123'))
36+
print(tag('li', 'first', 'second', class_='menu', id='#123'))

08-def-type-hints/birds/birds.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Bird:
2+
pass
3+
4+
class Duck(Bird): # <1>
5+
def quack(self):
6+
print('Quack!')
7+
8+
def alert(birdie): # <2>
9+
birdie.quack()
10+
11+
def alert_duck(birdie: Duck) -> None: # <3>
12+
birdie.quack()
13+
14+
def alert_bird(birdie: Bird) -> None: # <4>
15+
birdie.quack()

08-def-type-hints/birds/daffy.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from birds import *
2+
3+
daffy = Duck()
4+
alert(daffy) # <1>
5+
alert_duck(daffy) # <2>
6+
alert_bird(daffy) # <3>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Protocol # <1>
2+
3+
class GooseLike(Protocol):
4+
def honk(self, times: int) -> None: ... # <2>
5+
def swim(self) -> None: ...
6+
7+
8+
def alert(waterfowl: GooseLike) -> None: # <3>
9+
waterfowl.honk(2)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lake import alert
2+
3+
class Parrot:
4+
def honk(self, times: int) -> None: # <1>
5+
print('Honk! ' * times * 2)
6+
7+
8+
ze_carioca = Parrot()
9+
10+
alert(ze_carioca) # <2>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from lake import alert # <1>
2+
3+
class Swan: # <2>
4+
def honk(self, repetitions: int) -> None: # <3>
5+
print('Honk! ' * repetitions)
6+
7+
def swim(self) -> None: # <4>
8+
pass
9+
10+
11+
bella = Swan()
12+
13+
alert(bella) # <5>

08-def-type-hints/birds/woody.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from birds import *
2+
3+
woody = Bird()
4+
alert(woody)
5+
alert_duck(woody)
6+
alert_bird(woody)

0 commit comments

Comments
 (0)