With polymorphism and inheritance in the mainstream languages, the method signature still doesn't exactly tell you what you are going to get, so you have all of the pain of micromanaging type annotations and you still don't really get an invariant.
Also, Python has function annotations if your purpose is to document the signature without using docstrings. I'm unsure why you don't mention these because they are exactly analogous to what you say is straightforward.