-
Hello, I aplogize for the bad title formulation but I don't know how to phrase what I am looking for. I would be happy to change the title if you have suggestions. I have a small value container class ( The issue i am having is that I would like to create from typing import Callable, Generic, Optional, ParamSpec, TypeVar
T = TypeVar("T")
R = TypeVar("R")
P = ParamSpec("P")
class Field(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
def get(self) -> T:
return self._value
def set(self, value: T):
self._value = value
class Step:
def run(self):
...
class FuncStep(Step, Generic[P]):
def __init__(
self,
func: Callable[P, R],
output: Field[Optional[R]],
*args: P.args, # This should allow to use `func` arg names but wrapped in Field objects
**kwargs: P.kwargs, # This should allow to use `func` arg names but wrapped in Field objects
) -> None:
self.func = func
self.output = output
self.args = args
self.kwargs = kwargs
super().__init__()
def run(self):
args = [arg.get() for arg in self.args]
kwargs = {key: arg.get() for key, arg in self.kwargs.items()}
self.output.set(self.func(*args, **kwargs))
def test_func(a: int, b: int) -> int:
return a + b
if __name__ == "__main__":
# These fields are Field[int]
a_field, b_field, out_field = Field(1), Field(2), Field[Optional[int]](None)
#I would like this FuncStep to await the parameters output: Field[int], a: Field[int] and b: Field[int]
wrap_obj = FuncStep(test_func, output=out_field, a=a_field, b=b_field)
wrap_obj.run() # This runs without error
print(wrap_obj.output.get()) # We get the the right value
# This is correct for the typechecker but doesn't work and doesn't allow me to
# modify the after the init for anywhere else in the program
wrap_obj = FuncStep(test_func, output=out_field, a=8, b=7)
wrap_obj.run()
print(wrap_obj.output.get()) I guess a workaround solution would be to "cast" the class Field(Generic[T]):
def __init__(self, value: T) -> None:
self._value = value
def get(self) -> T:
return self._value
def set(self, value: T):
self._value = value
@property
def cast(self) -> T:
return cast(T, self)
...
if __name__ == "__main__":
# This works but is ugly, I would like not to have to use the `.cast` property
wrap_obj = FuncStep(test_func, output=out_field, a=a_field.cast, b=b_field.cast) Thank you for your help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
This sort of thing requires something like the previously proposed |
Beta Was this translation helpful? Give feedback.
This sort of thing requires something like the previously proposed
Map
construct. Unfortunately no concrete proposal or PEP has come out of it yet, so the thing you're doing right now is pretty much the only thing you can do. SQLAlchemy used a very similar workaround beforeTypeVarTuple
was available for theirRow
type, which had avalue
property that just returnedself
but cast it fromRow[T]
toT
.