Mypy produces incompatible signature error but Liskov Substitution Principle is satisfied

Viewed 817

The following inheritance structure satisfies the Liskov Substitution Principle (i.e., in this case, accepting any kwargs and not accepting any non-keyword args).

class Parent:
    def mymethod(self, **kwargs) -> None:
        print("Called Parent mymethod")
    
class Child(Parent):
    def mymethod(self, *, arg1: int, **kwargs) -> None:
        print("Called Child mymethod")

However, mypy produces an error:

error: Signature of "mymethod" incompatible with supertype "Parent"

Why?

1 Answers

Parent's mymethod claims to take a minimum of 0 keyword arguments. To understand this, take a look at this example:

def mymethod(**kwargs) -> None:
    pass

mymethod()

mypy reports success for this because no named keyword arguments are required. len(kwargs) here is 0.

Your example shows that Child's mymethod takes a minimum of 1 keyword argument, because arg1 is forced to be provided. For:

def mymethod(*, named_kwarg, **kwargs) -> None:
    pass 

mymethod()

mypy reports:

error: Missing named argument "named_kwarg" for "mymethod"

Do you now see why your error occurs? Your Parent's mymethod declares a minimum of 0 keyword arguments. Your Childs mymethod declare a minimum of 1 keyword argument. Liskov's Substitution Principle says that an instance of a superclass should be replaceable with an instance of the subclass, but since your subclass imposes stricter requirements than the superclass, mypy errors for your type hierarchy.

If mypy reported success, passing 0 keyword arguments would cause a runtime error if the instance of Parent you're dealing with also happened to be an instance of Child.

To further drive home the point, if we change Child's mymethod signature to:

def mymethod(self, *, arg1: Optional[int] = None, **kwargs) -> None:
    ...

mypy now shows no error for your hiearchy. This is because we've declared mymethod to take a minimum of now 0 keyword arguments instead of 1, making it as flexible as Parent requires under Liskov's Substitution Principle.

Related