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

Dieter Maurer dieter at handshake.de
Tue Aug 25 13:21:54 EDT 2020


Samuel Marks wrote at 2020-8-24 18:24 +1000:
>After a discussion on #python on Freenode, I'm here.
>
>The gist of it is:
>> Falc - Signature of method 'Pharm.foo()' does not match signature of base method in class 'Base'
>
>What's the right way of specialising the children and leaving the Base
>pretty much empty?
>
>Specifically I want:
>• All implementers to be forced to implement Base's method
>• Base to be able to do very basic things with kwargs, namely log it
>(to a file like stdout or a db)
>• Support for [at least] Python 3.6–3.9 (I don't think `Protocol` has
>been backported?)
>• Implementors to have access to the proper name, rather than having
>to unpack kwargs
>
>Should I be using a Base class? - Metaclass? - Something else
>entirely? - I know giving `b` a default value would resolve the
>[PyCharm] linter error… but I want it to be a required argument.
>
>Full example:
>
>from abc import ABC, abstractmethod
>
>
>class Base(ABC):
>    @abstractmethod
>    def foo(self, a, **kwargs):
> ...
>class Pharm(Base):
>    def foo(self, a, b):
> ...

Python make a distinction between positional and keyword
arguments. A positional argument is identified by its
position in the parameter list; a keyword argument is
identified by its name.

`**` introduces arbitrary keyword arguments. In a call, all
those arguments must be passed as "name=value".
In your case above, `b` is not a keyword argument and thus
is not matched by `**kwargs`. The error you observe is justified.

You can try:

class Base(ABC):
    @abstractmethod
    def foo(self, a, *args, **kwargs):
        ...

class Pharm(Base):
    def foo(self, a, b, *args, **kwargs):
        ...


Note that the base method signature allows arbitrary positional
and keyword arguments. As a consequence, derived methods must do
the same.

If this is not what you want, you might want to explore
the use of a decorator or a meta class rather than a base class.


More information about the Python-list mailing list