我无法让 pylance 或 mypy 对键入通用状态函数感到满意。如果我对状态机进行硬编码(不使用通用基类),我不会收到任何错误。在我的实际实现中,泛型类也不是抽象类,但我遇到了同样的问题,所以问题与此无关。
这是代码。请注意,这里的实现与我的状态机所做的无关。我刚刚创建了一些显示相同问题的最小的东西。我还努力让类型检查快乐,让特定的状态函数指定流的结尾(例如state_done
),而不是寻找 value None
。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import TypeVar, Generic, Optional, Callable
import random
_T = TypeVar("_T")
StateFunc = Optional[Callable[[_T], Optional["StateFunc"]]]
class GenericMachine(Generic[_T], ABC):
def __init__(self):
self._state: StateFunc[_T]
def run(self) -> None:
while self._state is not None:
self._state = self._state(self.get_next_event())
@abstractmethod
def get_next_event(self) -> _T:
pass
class Catch(GenericMachine[float]):
_MyStateFunc = StateFunc[float]
def __init__(self):
print("person has ball")
self._state: Catch._MyStateFunc = self._state_person_with_ball # ERROR 1
def get_next_event(self) -> float:
return random.random()
def _state_person_with_ball(self, r: float) -> Catch._MyStateFunc:
if r < 0.2:
return None
print("ball in air")
return self._state_ball_in_air # ERROR 2
def _state_ball_in_air(self, r: float) -> Catch._MyStateFunc:
print("dog has ball")
return self._state_dog_with_ball # ERROR 2
def _state_dog_with_ball(self, r: float) -> Catch._MyStateFunc:
if r < 0.2:
return None
print("person has ball")
return self._state_person_with_ball # ERROR 2
if __name__ == "__main__":
Catch().run()
编辑:我意识到 mypy 不会超过递归类型定义。当我刚刚声明StateFunc
返回一个Callable
.
Pylance 为 ERROR 1 报告以下内容(通过 VS Code):
Cannot assign member "_state" for type "Catch"
Expression of type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to member "_state" of class "Catch"
Type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to type "(_p0: float) -> StateFunc | None | None"
Type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to type "(_p0: float) -> StateFunc | None"
Type cannot be assigned to type "None"
Function return type "(_p0: float) -> StateFunc | None | None" is incompatible with type "StateFunc | None"
Type "(_p0: float) -> StateFunc | None | None" cannot be assigned to type "StateFunc | None"PylancereportGeneralTypeIssues
(variable) _state: (r: float) -> Unknown
它为错误 2 报告以下内容(通过 VS 代码):
Expression of type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to return type "(_p0: float) -> StateFunc | None | None"
Type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to type "(_p0: float) -> StateFunc | None | None"
Type "(r: float) -> (_p0: float) -> StateFunc | None | None" cannot be assigned to type "(_p0: float) -> StateFunc | None"
Type cannot be assigned to type "None"
Function return type "(_p0: float) -> StateFunc | None | None" is incompatible with type "StateFunc | None"
Type "(_p0: float) -> StateFunc | None | None" cannot be assigned to type "StateFunc | None"
Type "(_p0: float) -> StateFunc | None" cannot be assigned to type "StateFunc | None"PylancereportGeneralTypeIssues
(parameter) self: Catch
知道如何让 Pylance 开心吗?
更新:如果我将 StateFunc 定义如下,问题就会消失:
StateFunc = Optional[Callable[[_T], Any]]