ABC with abstractmethod: kwargs on Base, explicit names on implementation

Dieter Maurer dieter at handshake.de
Sat Aug 29 06:24:30 EDT 2020


Samuel Marks wrote at 2020-8-29 19:14 +1000:
>So there is no way to get a AOT error when the two functions aren't
>implemented, if the two functions have different required arguments on
>implementors?
>
>To paint this picture for why I need this, say the first is:
>
>class Base(ABC):
>    @abstractclass
>    def train(self, epochs):
>        asset epochs is not None and epochs > 0
>
>…and the implementation is:
>
>class TensorFlow(Base):
>    def train(self, learning_rate, epochs, callbacks, metrics, loss, optimizer):
>        super(Base, self).__init__(epochs=epochs)
>
>[+ docstrings and PEP484 types; excluded here for concision]
>
>So how do I enable this use-case? - Obviously it doesn't make sense to
>include these on the base class, and giving them default values
>probably doesn't make sense either.
>
>You're saying I shouldn't be using ABC for this. So what should I be using?

What is your purpose to use a base class in the first place --
and especially one where `train` has this signature?

You signal with this base class, that it makes sense to
call `train` with a single positional argument.
But `train` in the derived class cannot be called in this way.

Base classes are there to capture common features of several
related classes. In your example above, this is not the case.
Do not use base classes in this way.

>The requirement I'm trying to enforce is that each implementor has a
>`train` callable attached.
>Preferably with one required field (but this is just a nice-to-have).

Read the Python documentation about metaclasses and the special methods
related to class derivation. Both approaches would allow you
to check whatever you want.

> ...
>However if I only have functions which accept an instance of a class
>as the argument, then that will make it less user-friendly to the API
>caller. So I really am looking for handling both interfaces in a
>straightforward manner.

Any system makes some things easy and other things difficult.
Try to stay with the essential paradigms underlaying the system --
in order to use the easy things whenever possible.

In your case, this means that the signature of an overriding
method must be quite similar to that of the overridden method.


More information about the Python-list mailing list