dimanche 24 septembre 2023

Conditional `@abstractmethod`

What's a good design-pattern / solution for the following problem?

Context: I want to write a Protocol "IVP_Generator" for classes that represent initial value problems. These classes must provide a function solve_ivp that solves the IVP for some time interval. Now, in the by far most common case, one defines a system and uses an off-the-shelve solver. So I want the protocol to look something like this:

class IVP_Generator(Protocol[T]):
    """T some array-type."""

    @property
    def system(self) -> Callable[[T, T], T]:
        """Represents the vector field f(t, x(t)), if applicable."""
        return NotImplemented

    def solve_ivp(self, t: T, y0: T) -> T:
        """Return solution y[t] of the IVP."""
        if self.system is NotImplemented:
            raise NotImplementedError
        return default_solver(self.system, t, y0)

Now, I don't really want to make system an @abstractmethod because there are some cases I want to cover where the dynamics are not given by an ODE. In these cases, solve_ivp should be overwritten by the subclass appropriately.

So really the behavior I want is:

  • If a subclass does not implement system, it must implement solve_ivp
  • If a subclass implements system it can choose to implement solve_ivp or not.

Is it possible to make @abstractmethod conditional this way? Or should I do something else altogether? I'd rather like to avoid having multiple Protocols.

Aucun commentaire:

Enregistrer un commentaire