В качестве предупреждения, мне неясно, как именно выглядит ваш код. У вас есть несколько разных версий Foo
, и я не уверен, какую именно вы пытаетесь подклассить - в вашем вопросе отсутствует минимально воспроизводимый пример .
Но я предполагаю, что вы пытаетесь сделать что-то подобное?
class Foo:
def bar(self, *baz: float) -> str:
raise NotImplementedError
class SubFoo(Foo):
def bar(self, baz: float) -> str:
pass
Если это так, проблема заключается в том, что согласно сигнатуре базового класса это будет Разрешается делать что-то подобное, поскольку Foo.bar(...)
определено для приема переменного числа аргументов.
f = Foo()
f.bar(1, 2, 3, 4, 5, 6, 7, 8)
Но если мы попытаемся использовать ваш подкласс вместо Foo, этот код потерпит неудачу, поскольку он принимает только один аргумент.
Эта идея о том, что подкласс всегда должен быть в состоянии занять место родительского класса, не вызывая ошибок типа и не нарушая существующие предварительные условия и постусловия вашего кода, известна как замена Лискова принцип .
Но в таком случае зачем делать следующую проверку типа?
class Foo:
bar: Callable[..., str]
class SubFoo(Foo):
def bar(self, baz: float) -> str:
pass
Это потому, что поскольку подпись родительского типа Callable[..., str]
, mypy фактически заканчивается пропуская проверку аргументов функции вообще. ...
в основном говорит: «Пожалуйста, не беспокойтесь о проверке типов, связанной с моими аргументами».
Это похоже на то, как использование типа Any
позволяет смешивать типы Dynami c со stati c из них. Точно так же Callable[..., str]
позволяет вам express вызывать с динамическими / неопределенными сигнатурами.
Сравните это со следующей программой:
class Foo:
def bar(self, *args: Any, **kwargs: Any) -> str:
pass
class SubFoo(Foo):
def bar(self, baz: float) -> str:
pass
В отличие от предыдущей, эта программа делает не проверка типа - хотя Foo.bar
все еще может принимать любые аргументы, «структура» аргументов в этом случае не остается гибкой, и mypy теперь будет настаивать на том, что ваш подкласс также должен быть способен принимать произвольное число Аргументы.
В качестве заключительного замечания важно отметить, что ни одно из этого поведения не имеет никакого отношения к тому, определены ли ваши подсказки типа в заглушке или нет. Скорее, все сводится к тому, каковы фактические типы ваших функций.