[英]How do I get `mypy` to recognize that an argument of a function needs to be a subclass of a particular base class?
How do I get mypy
to recognize that an argument of a function needs to be a subclass of a particular base class?如何让mypy
认识到 function 的参数需要是特定基础 class 的子类? Consider the following:考虑以下:
# main.py
class A: ...
class B(A):
def f(self, x):
print(x)
class C(A):
def f(self, x):
print(x, "in C")
# test.py
def call_f(instance):
instance.f("Hello")
if __name__=="__main__":
from main import B, C
b = B()
call_f(b)
c = C()
call_f(c)
As shown in main.py
, all subclasses of A
implement a method f
.如main.py
所示, A
的所有子类都实现了一个方法f
。 call_f
in test.py
takes an instance of one of the subclasses of A
and calls this method. test.py
中的call_f
采用A
的子类之一的实例并调用此方法。 An example of this is shown in the if __name__ == "__main__":
section of test.py
. test.py
的if __name__ == "__main__":
部分显示了一个示例。
One way to type hint the definition in test.py
would be the following:在test.py
中键入提示定义的一种方法如下:
# test_typed.py
from typing import Union
from main import B, C
def call_f(instance: Union[B, C]) -> None:
instance.f("Hello")
if __name__=="__main__":
from main import B, C
b = B()
call_f(b)
c = C()
call_f(c)
However, the disadvantage here is that I have to keep adding every new subclass of A
into the function annotation of call_f
which seems repetitive.但是,这里的缺点是我必须不断地将A
的每个新子类添加到 call_f 的call_f
注释中,这似乎是重复的。
Is there a better way to do this?有一个更好的方法吗?
I suppose that taking a stab at an answer isn't a bad idea at this point, since I have enough information from the comments.我想在这一点上尝试回答并不是一个坏主意,因为我从评论中获得了足够的信息。
You need to first enforce that f
is implemented by subclasses of A
.您需要首先强制f
由A
的子类实现。 Otherwise, you could implement a subclass that doesn't implement f
, and static typechecking would (rightfully) point out that there is nothing preventing that from occurring.否则,您可以实现一个不实现f
的子类,并且 static 类型检查会(正确地)指出没有什么可以阻止这种情况的发生。 You could use Union[B, C]
if you only wanted some subclasses to implement f
, but you've already stated that this is undesirable for extensibility reasons.如果您只希望某些子类实现f
,则可以使用Union[B, C]
,但您已经说过出于可扩展性的原因,这是不可取的。
What you should do is have the function accept instances of the superclass A
, and raise an error whenever f
as defined in the superclass is invoked:您应该做的是让 function 接受超类A
实例,并在调用超类中定义的f
时引发错误:
class A:
def f(self, x):
raise NotImplementedError("A.f is not implemented, because A is an abstract class!")
class B(A):
def f(self, x):
print(x)
class C(A):
def f(self, x):
print(x, "in C")
Then, call_f()
would look like the following:然后, call_f()
将如下所示:
def call_f(instance: A) -> None:
instance.f("Hello")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.