在Python中键入泛型状态函数

2024-10-01 02:26:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我无法让pylance或mypy对键入泛型状态函数感到满意。如果我硬编码状态机(不使用泛型基类),我不会得到任何错误。在我的实际实现中,泛型类不是一个抽象类,但我遇到了相同的问题,因此这个问题与此无关

这是密码。请注意,这里的实现与状态机的功能无关。我只是创造了一些极小的东西,显示了同样的问题。我还努力使类型检查愉快地使用一个特定的状态函数来指定流的结尾(例如state_done),而不是查找值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()

EDIT:我意识到mypy无法通过递归类型定义。当我声明StateFunc返回一个Callable时,我在mypy上得到了类似的错误

Pylance报告以下错误1(通过VS代码):

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

知道如何让派伦斯快乐吗

更新:如果我按如下方式定义StateFunc,问题就会消失:

StateFunc = Optional[Callable[[_T], Any]]


Tags: toselfnonereturntypebefloatstate