Skip to content

Commit 1689eec

Browse files
committed
ch15: draft examples
1 parent 5312d4f commit 1689eec

19 files changed

+501
-36
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from typing import TypeVar, Generic
2+
3+
4+
class Beverage:
5+
"""Any beverage"""
6+
7+
8+
class Juice(Beverage):
9+
"""Any fruit juice"""
10+
11+
12+
class OrangeJuice(Juice):
13+
"""Delicious juice Brazilian oranges"""
14+
15+
16+
class Coak(Beverage):
17+
"""Secret formula with lots of sugar"""
18+
19+
20+
BeverageT = TypeVar('BeverageT', bound=Beverage)
21+
JuiceT = TypeVar('JuiceT', bound=Juice)
22+
23+
24+
class BeverageDispenser(Generic[BeverageT]):
25+
26+
beverage: BeverageT
27+
28+
def __init__(self, beverage: BeverageT) -> None:
29+
self.beverage = beverage
30+
31+
def dispense(self) -> BeverageT:
32+
return self.beverage
33+
34+
35+
class JuiceDispenser(BeverageDispenser[JuiceT]):
36+
pass
37+
38+
39+
class Cafeteria:
40+
def __init__(self, dispenser: BeverageDispenser[JuiceT]):
41+
self.dispenser = dispenser
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from cafeteria import (
2+
Cafeteria,
3+
BeverageDispenser,
4+
JuiceDispenser,
5+
Juice,
6+
OrangeJuice,
7+
Coak,
8+
)
9+
10+
orange = OrangeJuice()
11+
12+
orange_dispenser: JuiceDispenser[OrangeJuice] = JuiceDispenser(orange)
13+
14+
juice: Juice = orange_dispenser.dispense()
15+
16+
soda = Coak()
17+
18+
## Value of type variable "JuiceT" of "JuiceDispenser" cannot be "Coak"
19+
# soda_dispenser = JuiceDispenser(soda)
20+
21+
soda_dispenser = BeverageDispenser(soda)
22+
23+
arnold_hall = Cafeteria(soda_dispenser)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from collections.abc import Collection, Sequence
2+
3+
col_int: Collection[int]
4+
5+
seq_int: Sequence[int] = (1, 2, 3)
6+
7+
## Incompatible types in assignment
8+
## expression has type "Collection[int]"
9+
## variable has type "Sequence[int]"
10+
# seq_int = col_int
11+
12+
col_int = seq_int
13+
14+
## List item 0 has incompatible type "float"
15+
## expected "int"
16+
# col_int = [1.1]
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import random
2-
from typing import Iterable, TYPE_CHECKING, List
1+
from typing import TYPE_CHECKING
32

43
from erp import EnterpriserRandomPopper
54
import randompop
@@ -9,7 +8,6 @@ def test_issubclass() -> None:
98
assert issubclass(EnterpriserRandomPopper, randompop.RandomPopper)
109

1110

12-
1311
def test_isinstance_untyped_items_argument() -> None:
1412
items = [1, 2, 3]
1513
popper = EnterpriserRandomPopper(items) # [int] is not required

15-more-types/gen_contra.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
"""
2+
In ``Generator[YieldType, SendType, ReturnType]``,
3+
``SendType`` is contravariant.
4+
The other type variables are covariant.
5+
6+
This is how ``typing.Generator`` is declared::
7+
8+
class Generator(Iterator[T_co], Generic[T_co, T_contra, V_co]):
9+
10+
(from https://docs.python.org/3/library/typing.html#typing.Generator)
11+
12+
"""
13+
14+
from typing import Generator
15+
16+
17+
# Generator[YieldType, SendType, ReturnType]
18+
19+
def gen_float_take_int() -> Generator[float, int, str]:
20+
received = yield -1.0
21+
while received:
22+
received = yield float(received)
23+
return 'Done'
24+
25+
26+
def gen_float_take_float() -> Generator[float, float, str]:
27+
received = yield -1.0
28+
while received:
29+
received = yield float(received)
30+
return 'Done'
31+
32+
33+
def gen_float_take_complex() -> Generator[float, complex, str]:
34+
received = yield -1.0
35+
while received:
36+
received = yield abs(received)
37+
return 'Done'
38+
39+
# Generator[YieldType, SendType, ReturnType]
40+
41+
g0: Generator[float, float, str] = gen_float_take_float()
42+
43+
g1: Generator[complex, float, str] = gen_float_take_float()
44+
45+
## Incompatible types in assignment
46+
## expression has type "Generator[float, float, str]"
47+
## variable has type "Generator[int, float, str]")
48+
# g2: Generator[int, float, str] = gen_float_take_float()
49+
50+
51+
# Generator[YieldType, SendType, ReturnType]
52+
53+
g3: Generator[float, int, str] = gen_float_take_float()
54+
55+
## Incompatible types in assignment
56+
## expression has type "Generator[float, float, str]"
57+
## variable has type "Generator[float, complex, str]")
58+
## g4: Generator[float, complex, str] = gen_float_take_float()
59+

15-more-types/petbox/petbox.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from typing import TypeVar, Generic, Any
2+
3+
4+
class Pet:
5+
"""Domestic animal kept for companionship."""
6+
7+
8+
class Dog(Pet):
9+
"""Canis familiaris"""
10+
11+
12+
class Cat(Pet):
13+
"""Felis catus"""
14+
15+
16+
class Siamese(Cat):
17+
"""Cat breed from Thailand"""
18+
19+
20+
T = TypeVar('T')
21+
22+
23+
class Box(Generic[T]):
24+
def put(self, item: T) -> None:
25+
self.contents = item
26+
27+
def get(self) -> T:
28+
return self.contents
29+
30+
31+
T_contra = TypeVar('T_contra', contravariant=True)
32+
33+
34+
class InBox(Generic[T_contra]):
35+
def put(self, item: T) -> None:
36+
self.contents = item
37+
38+
39+
T_co = TypeVar('T_co', covariant=True)
40+
41+
42+
class OutBox(Generic[T_co]):
43+
def __init__(self, contents: Any):
44+
self.contents = contents
45+
46+
def get(self) -> Any:
47+
return self.contents
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from typing import TYPE_CHECKING
2+
3+
from petbox import *
4+
5+
6+
cat_box: Box[Cat] = Box()
7+
8+
si = Siamese()
9+
10+
cat_box.put(si)
11+
12+
animal = cat_box.get()
13+
14+
#if TYPE_CHECKING:
15+
# reveal_type(animal) # Revealed: petbox.Cat*
16+
17+
18+
################### Covariance
19+
20+
out_box: OutBox[Cat] = OutBox(Cat())
21+
22+
out_box_si: OutBox[Siamese] = OutBox(Siamese())
23+
24+
## Incompatible types in assignment
25+
## expression has type "OutBox[Cat]"
26+
# variable has type "OutBox[Siamese]"
27+
# out_box_si = out_box
28+
29+
out_box = out_box_si
30+
31+
################### Contravariance
32+
33+
in_box: InBox[Cat] = InBox()
34+
35+
in_box_si: InBox[Siamese] = InBox()
36+
37+
in_box_si = in_box
38+
39+
## Incompatible types in assignment
40+
## expression has type "InBox[Siamese]"
41+
## variable has type "InBox[Cat]"
42+
# in_box = in_box_si
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from randompick_generic import GenericRandomPicker
55

66

7-
class LottoPicker():
7+
class LottoPicker:
88
def __init__(self, items: Iterable[int]) -> None:
99
self._items = list(items)
1010
random.shuffle(self._items)

0 commit comments

Comments
 (0)