我想对一个方法进行类型提示,该方法可以接收对 A 或 A 的子类进行操作的 Callable:
def do(f: Callable[[A], None])
我也试过:
def do(f: Callable[[typing.Type[A]], None])
一个完整的虚拟示例如下所示:
class A:
n = 1
class B(A):
n = 2
def something_a(x: A):
print(x.n)
def something_b(x: B):
print(x.n)
def do(f: Callable[[A], None]):
f(B())
do(something_a) # ok
do(something_b) # PyCharm type check warnning
最佳答案
正如宫城先生指出的那样—— 类型检查警告是正确的。
B
继承自 A
,所以 something_a(x: A)
可以同时接受 A
和 B
,而 something_b(x: B)
只能接受 B
。 (协方差)
如果我们将 something_b(x: B)
传递给 do(f: Callable[[A], None])
,我们允许 something_b(x: B)
接受 A
- 它不能。所以 something_b(x: B)
不能替代 something_a(x: A)
。另一方面,将 something_a(x: A)
传递给需要 Callable[[B], None]
的函数是可以的。 (逆变)
做什么? - 使用泛型
AType = TypeVar('AType', bound=A)
def do_fixed(f: Callable[[AType], None]):
pass
do_fixed(something_a) # ok
do_fixed(something_b) # ok
虽然我们确实收到了传递其他类型可调用对象的警告:
class C: # not derived from A
n = 1
def something_c(x: C):
print(x.n)
do_fixed(something_c) # type check warning
但我们仍然需要确保我们没有将 A
传递给 something_b
,这可以通过以下方式实现:
def do_safer(f: Callable[[AType], None], v: AType):
f(v)
do_safer(something_a, A()) # ok
do_safer(something_a, B()) # ok
do_safer(something_b, A()) # type check warning
do_safer(something_b, B()) # ok
关于python - 为支持子类的 Callable 类型提示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65927533/