squ*_*rel 5 python python-typing
我想在 Python 中创建等价物:
static class Event {}
static class MyEvent extends Event {}
interface Filter<E extends Event> {
boolean filter(E event);
}
static class MyFilter implements Filter<MyEvent> {
@Override public boolean filter(MyEvent event) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的尝试(mypy-play):
from typing import TypeVar, Protocol
class Event:
pass
class MyEvent(Event):
pass
E = TypeVar("E", bound=Event)
class Filter(Protocol[E]):
def filter(self, event: E) -> bool:
raise NotImplementedError
class MyFilter(Filter):
def filter(self, event: MyEvent) -> bool: # should be ok
raise NotImplementedError
class BadFilter(Filter):
def filter(self, event: object) -> bool: # should fail
raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)
...失败了main.py:11: error: Invariant type variable 'E' used in protocol where contravariant one is expected。除非我误解了,Java 似乎对一个不变的没问题,这也是我的想法;我不希望各种Filters 相互兼容。在任何情况下,拍打contravariant=True到T 也不管用。所以,
为什么协议需要逆变变量?而且,如何进行此 Python 代码类型检查?
协议不允许这样做,因为它破坏了子类型的传递性。参见PEP 544。
如果您有以下两个类:
class A:
def method(self, arg: int):
pass
class B(A):
def method(self, arg: object):
pass
Run Code Online (Sandbox Code Playgroud)
thenB是 的有效子类A,因为B.method可以接受任何参数A.methodcan。但是,如果您可以引入以下协议:
T = typing.TypeVar('T')
class Proto(typing.Protocol[T]):
def method(self, arg: T):
pass
Run Code Online (Sandbox Code Playgroud)
thenA会满足Proto[int],但B不会,因为 的不变性T。