I am trying to find the most elegant way to help IntelliSense catch the expected set of parameters for the callables.
Consider the following piece of code:
class Box:
def __init__(self, f: callable) -> None:
self.f: callable = f
def callF(self):
self.f(self, 5, 6, 77, 65)
As one can see, the callable object f
was not explicitly defined in the parameters.
I can try to fix it with the delegate:
from __future__ import annotations
class Box:
class BoxFDelegate:
def f(self, a:int, b:int, c:int, d:int):
pass
def __init__(self, f: Box.BoxFDelegate.f) -> None:
self.f: Box.BoxFDelegate.f = f
def callF(self):
self.f(self, 5, 6, 77, 65)
The delegate pattern is great, but it needs to subclass the delegate elsewhere of the body of code:
class D(Box.BoxFDelegate):
def f(self, a:int, b:int, c:int, d:int):
...
class Main:
def boxing():
boxDelegate = D()
box = Box(boxDelegate)
...
As a possible variant of the delegating, is the including the delegate method into the Main class:
class Main(Box.BoxFDelegate):
def boxing():
box = Box(self.f)
...
def f(self, a:int, b:int, c:int, d:int):
...
This notation is shorter, but what if I have many different class Box
instances?
In the perfect world, I can accomplish such a problem with:
class Main(Box.BoxFDelegate):
def boxing():
boxes = [
Box(lambda a, b, c, d: ...),
Box(lambda a, b, c, d: ...),
Box(lambda a, b, c, d: ...),
]
Unfortunately, such a way is write-only.
How to be concise in types and not be brutally beaten by developers who will attempt to maintain the code later?
Please look at the comment from @SuperStormer. It should result in something like this:
from __future__ import annotations
from typing import Callable
class Box:
def __init__(self, f: Callable[[Box, int, int, int, int], None]) -> None:
self.f = f
def call_f(self) -> None:
self.f(self, 5, 6, 77, 65)