-
Notifications
You must be signed in to change notification settings - Fork 208
/
Copy pathabc_example.py
63 lines (46 loc) · 1.25 KB
/
abc_example.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
def abstractmethod(f):
f.__isabstract__ = True
return f
def abstractmethods(cls):
seen = set()
abstract = []
while isinstance(cls, ABCMeta):
for key, val in vars(cls).items():
if key in seen:
continue
seen.add(key)
if getattr(val, '__isabstract__', False):
abstract.append(key)
# object is not ABCMeta so mro will have at least 2 entries
cls = cls.__mro__[1]
return abstract
class ABCMeta(type):
def __call__(abccls, *args, **kwargs): # called when you A()
print("call", abccls, args, kwargs)
abstract = abstractmethods(abccls)
if abstract:
raise TypeError('no implementation for: ' + ', '.join(abstract))
return super().__call__(*args, **kwargs)
class ABC(metaclass=ABCMeta):
pass
class A(ABC):
def __init__(self, *args, **kwargs):
print("init", self, args, kwargs)
@abstractmethod
def f(self):
pass
@abstractmethod
def g(self):
pass
class B(A):
def f(self):
pass
def g(self):
pass
def main():
# A() # Error: abstract f,g
b = B()
print(f'{type(b)=}')
print(f'{type(B)=}')
if __name__ == '__main__':
main()