-
Notifications
You must be signed in to change notification settings - Fork 0
/
typevar_generic.py
102 lines (58 loc) · 1.61 KB
/
typevar_generic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
from typing import TypeVar, Type, Generic, List
class Base:
pass
class A(Base):
def __init__(self, a):
self.a = a
class B(Base):
def __init__(self, b):
self.b = b
class C:
def __init__(self, c):
self.c = c
S = TypeVar("S", bound=Base)
def instantiate(cls: Type[S], *args, **kwargs) -> S:
return cls(*args, **kwargs)
# valid, type checkers know that a is of type A
a = instantiate(A, 1)
print(a.a)
# valid, type checkers know that b is of type B
b = instantiate(B, 2)
print(b.b)
# type-invalid, but type checkers still know that c is of type C
c = instantiate(C, 3)
print(c.c)
class Factory(Generic[S]):
@staticmethod
def instantiate(cls: Type[S], *args, **kwargs) -> S:
return cls(*args, **kwargs)
f: Factory[A] = Factory()
# valid
ia = f.instantiate(A, "F1")
print(ia.a)
# type-invalid, the factory is expected to be used only with A
ib = f.instantiate(B, "F2") # type: ignore
print(ib.b) # type: ignore
# valid factory
g: Factory[B] = Factory()
# type-invalid factory, since we only allow Factories to accept anything based on Base
h: Factory[C] = Factory()
T = TypeVar("T", str, int)
def add(a: T, b: T) -> T:
return a+b
print(add(1, 2))
print(add("a", "b"))
# type-invalid (and won't run, but that's not the point)
# print(add(1, "a"))
def append_and_print_sum(l: List[T], a: T):
l.append(a)
s = l.pop(0)
while len(l):
s += l.pop(0)
print(s)
# valid
append_and_print_sum([1, 2, 3], 4)
# valid
append_and_print_sum(["a", "b", "c"], "d")
# type-invalid (and won't run...)
# append_and_print_sum(["a", "b", "c"], 7)