Simple example of my problem:
JavaScript
x
31
31
1
class AbstractService:
2
subscribers = []
3
4
@classmethod
5
def subscribe(cls, service):
6
service.subscribers.append(cls)
7
8
@classmethod
9
@abstractmethod
10
def notify(cls, payload):
11
raise NotImplementedError(f"{cls.__name__} not implemented notify()")
12
13
14
class ServiceA(AbstractService):
15
16
@classmethod
17
def notify(cls, payload):
18
pass
19
20
21
class ServiceB(AbstractService):
22
23
@classmethod
24
def notify(cls, payload):
25
pass
26
27
28
ServiceB.subscribe(ServiceA)
29
30
ServiceA.notify({'message': 'hello'})
31
The issue is that all services in this instance will share subscribers, hence my solution was to create a function that returns the abstract service as such:
JavaScript
1
33
33
1
def get_abstract_service():
2
3
class AbstractService:
4
subscribers = []
5
6
@classmethod
7
def subscribe(cls, service):
8
service.subscribers.append(cls)
9
10
@classmethod
11
@abstractmethod
12
def notify(cls, payload):
13
raise NotImplementedError(f"{cls.__name__} not implemented notify()")
14
15
return AbstractService
16
class ServiceA(get_abstract_service()):
17
18
@classmethod
19
def notify(cls, payload):
20
pass
21
22
23
class ServiceB(get_abstract_service()):
24
25
@classmethod
26
def notify(cls, payload):
27
pass
28
29
30
ServiceB.subscribe(ServiceA)
31
32
ServiceA.notify({'message': 'hello'})
33
This now works because subscribers are unique to each class inheriting the abstract service.
Issues
Is this correct for python, or is the pattern wrong if so what would be the norm in this situation
How do I handle typing for AbstractService if my solution is correct (for any function that requires that type to be passed to it)
Advertisement
Answer
i would approach it like this:
JavaScript
1
10
10
1
from __future__ import annotations
2
3
4
class AbstractService:
5
subscribers: list[AbstractService]
6
7
def __init_subclass__(cls, **kw):
8
super().__init_subclass__(**kw)
9
cls.subscribers = []
10
it sets a new subscribers
instance on each class after creation.
edit: additionally this handles typing for you as well by using from __future__ import annotations
e.g.
JavaScript
1
4
1
class C:
2
def f(self) -> C:
3
4