Overriding statically typed methods

When overriding a statically typed method, mypy checks that theoverride has a compatible signature:

  1. class Base:
  2. def f(self, x: int) -> None:
  3. ...
  4.  
  5. class Derived1(Base):
  6. def f(self, x: str) -> None: # Error: type of 'x' incompatible
  7. ...
  8.  
  9. class Derived2(Base):
  10. def f(self, x: int, y: int) -> None: # Error: too many arguments
  11. ...
  12.  
  13. class Derived3(Base):
  14. def f(self, x: int) -> None: # OK
  15. ...
  16.  
  17. class Derived4(Base):
  18. def f(self, x: float) -> None: # OK: mypy treats int as a subtype of float
  19. ...
  20.  
  21. class Derived5(Base):
  22. def f(self, x: int, y: int = 0) -> None: # OK: accepts more than the base
  23. ... # class method

Note

You can also vary return types covariantly in overriding. Forexample, you could override the return type Iterable[int] with asubtype such as List[int]. Similarly, you can vary argument typescontravariantly – subclasses can have more general argument types.

You can also override a statically typed method with a dynamicallytyped one. This allows dynamically typed code to override methodsdefined in library classes without worrying about their typesignatures.

As always, relying on dynamically typed code can be unsafe. There is noruntime enforcement that the method override returns a value that iscompatible with the original return type, since annotations have noeffect at runtime:

  1. class Base:
  2. def inc(self, x: int) -> int:
  3. return x + 1
  4.  
  5. class Derived(Base):
  6. def inc(self, x): # Override, dynamically typed
  7. return 'hello' # Incompatible with 'Base', but no mypy error