Skip to content

Commit f248baf

Browse files
committed
adding sentinel metaclass example
1 parent 8a330d8 commit f248baf

File tree

14 files changed

+220
-1
lines changed

14 files changed

+220
-1
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from typing import TypeVar, TYPE_CHECKING
2+
from decimal import Decimal
3+
4+
# tag::TYPEVAR_RESTRICTED[]
5+
RT = TypeVar('RT', float, Decimal)
6+
7+
def triple1(a: RT) -> RT:
8+
return a * 3
9+
10+
res1 = triple1(1, 2)
11+
12+
if TYPE_CHECKING:
13+
reveal_type(res1)
14+
# end::TYPEVAR_RESTRICTED[]
15+
16+
# tag::TYPEVAR_BOUNDED[]
17+
BT = TypeVar('BT', bound=float)
18+
19+
def triple2(a: BT) -> BT:
20+
return a * 3
21+
22+
res2 = triple2(1, 2)
23+
24+
if TYPE_CHECKING:
25+
reveal_type(res2)
26+
# tag::TYPEVAR_BOUNDED[]
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Compostable(Biodegradable):
4141

4242
class TrashCan(Generic[T_contra]):
4343
def put(self, trash: T_contra) -> None:
44-
"""Store trash until dumped..."""
44+
"""Store trash until dumped."""
4545

4646

4747
class Cafeteria:
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# tag::TRASH_TYPES[]
2+
from typing import TypeVar, Generic
3+
4+
class Refuse: # <1>
5+
"""Any refuse."""
6+
7+
class Biodegradable(Refuse):
8+
"""Biodegradable refuse."""
9+
10+
class Compostable(Biodegradable):
11+
"""Compostable refuse."""
12+
13+
T_contra = TypeVar('T_contra', contravariant=True) # <2>
14+
15+
class TrashCan(Generic[T_contra]): # <3>
16+
def put(self, refuse: T_contra) -> None:
17+
"""Store trash until dumped."""
18+
19+
def deploy(trash_can: TrashCan[Biodegradable]):
20+
"""Deploy a trash can for biodegradable refuse."""
21+
# end::TRASH_TYPES[]
22+
23+
24+
################################################ contravariant trash can
25+
26+
27+
# tag::DEPLOY_TRASH_CANS[]
28+
bio_can: TrashCan[Biodegradable] = TrashCan()
29+
deploy(bio_can)
30+
31+
trash_can: TrashCan[Refuse] = TrashCan()
32+
deploy(trash_can)
33+
# end::DEPLOY_TRASH_CANS[]
34+
35+
36+
################################################ more specific trash can
37+
38+
# tag::DEPLOY_NOT_VALID[]
39+
compost_can: TrashCan[Compostable] = TrashCan()
40+
deploy(compost_can)
41+
# end::DEPLOY_NOT_VALID[]
42+
43+
## Argument 1 to "deploy" has
44+
## incompatible type "TrashCan[Compostable]"
45+
## expected "TrashCan[Biodegradable]"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 from Brazilian oranges."""
14+
15+
16+
# tag::BEVERAGE_TYPES[]
17+
T_co = TypeVar('T_co', covariant=True) # <1>
18+
19+
20+
class BeverageDispenser(Generic[T_co]): # <2>
21+
def __init__(self, beverage: T_co) -> None:
22+
self.beverage = beverage
23+
24+
def dispense(self) -> T_co:
25+
return self.beverage
26+
27+
def install(dispenser: BeverageDispenser[Juice]) -> None: # <3>
28+
"""Install a fruit juice dispenser."""
29+
# end::BEVERAGE_TYPES[]
30+
31+
################################################ covariant dispenser
32+
33+
# tag::INSTALL_JUICE_DISPENSERS[]
34+
juice_dispenser = BeverageDispenser(Juice())
35+
install(juice_dispenser)
36+
37+
orange_juice_dispenser = BeverageDispenser(OrangeJuice())
38+
install(orange_juice_dispenser)
39+
# end::INSTALL_JUICE_DISPENSERS[]
40+
41+
################################################ not a juice dispenser
42+
43+
beverage_dispenser = BeverageDispenser(Beverage())
44+
45+
## Argument 1 to "install" has
46+
## incompatible type "BeverageDispenser[Beverage]"
47+
## expected "BeverageDispenser[Juice]"
48+
install(beverage_dispenser)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# tag::BEVERAGE_TYPES[]
2+
from typing import TypeVar, Generic
3+
4+
class Beverage: # <1>
5+
"""Any beverage."""
6+
7+
class Juice(Beverage):
8+
"""Any fruit juice."""
9+
10+
class OrangeJuice(Juice):
11+
"""Delicious juice from Brazilian oranges."""
12+
13+
T = TypeVar('T') # <2>
14+
15+
class BeverageDispenser(Generic[T]): # <3>
16+
"""A dispenser parameterized on the beverage type."""
17+
def __init__(self, beverage: T) -> None:
18+
self.beverage = beverage
19+
20+
def dispense(self) -> T:
21+
return self.beverage
22+
23+
def install(dispenser: BeverageDispenser[Juice]) -> None: # <4>
24+
"""Install a fruit juice dispenser."""
25+
# end::BEVERAGE_TYPES[]
26+
27+
################################################ exact type
28+
29+
# tag::INSTALL_JUICE_DISPENSER[]
30+
juice_dispenser = BeverageDispenser(Juice())
31+
install(juice_dispenser)
32+
# end::INSTALL_JUICE_DISPENSER[]
33+
34+
35+
################################################ variant dispenser
36+
37+
# tag::INSTALL_BEVERAGE_DISPENSER[]
38+
beverage_dispenser = BeverageDispenser(Beverage())
39+
install(beverage_dispenser)
40+
## Argument 1 to "install" has
41+
## incompatible type "BeverageDispenser[Beverage]"
42+
## expected "BeverageDispenser[Juice]"
43+
# end::INSTALL_BEVERAGE_DISPENSER[]
44+
45+
46+
################################################ variant dispenser
47+
48+
# tag::INSTALL_ORANGE_JUICE_DISPENSER[]
49+
orange_juice_dispenser = BeverageDispenser(OrangeJuice())
50+
install(orange_juice_dispenser)
51+
# end::INSTALL_ORANGE_JUICE_DISPENSER[]
52+
## Argument 1 to "install" has
53+
## incompatible type "BeverageDispenser[OrangeJuice]"
54+
## expected "BeverageDispenser[Juice]"
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)