Python中的存在类型?

2024-09-29 01:34:28 发布

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

我有一个泛型类(比如Automata[S]),我希望另一个非泛型类(比如Test)将Automata[S]作为一些S的字段(即,我希望将∃S. Automata[S]作为字段)

我的第一次尝试是使用unsubscribedAutomata类型对字段进行注释,如下所示。但是deltais_finale的应用程序不是类型安全的,因为类型参数S变成了Any

import abc
from typing import Generic, TypeVar


S = TypeVar('S')


class Automata(Generic[S], metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def initial_state(self) -> S:
        raise NotImplementedError()

    @abc.abstractmethod
    def delta(self, state: S, x: int) -> S:
        raise NotImplementedError()

    @abc.abstractmethod
    def is_final(self, state: S) -> bool:
        raise NotImplementedError()


class Counter(Automata[int]):
    def initial_state(self) -> int:
        return 0

    def delta(self, state: int, x: int) -> int:
        return state + x

    def is_final(self, state: int) -> bool:
        return state >= 10


class Test:
    automata: Automata

    def __init__(self, automata: Automata[S]):
        self.automata = automata

    def test(self) -> bool:
        s0 = self.automata.initial_state()
        # reveal_type(self.automata) #=> Automata[Any]
        # reveal_type(s0) #=> Any
        s1 = self.automata.delta(s0, 1)
        s2 = self.automata.delta(s1, 2)
        s3 = self.automata.delta(s2, 3)
        return self.automata.is_final(s3)


test = Test(Counter())
test.test()

我的另一个尝试是使用同构∃X. F(X) ≅ ∀R. (∀X. F(X) → R) → R,如下所示。它看起来是类型安全的,因为显示的类型不是Any,但是为每次写入continuation而对Cont进行子类化是冗长且有点复杂的

import abc
from typing import Generic, TypeVar


S = TypeVar('S')
R = TypeVar('R')


class Automata(Generic[S], metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def initial_state(self) -> S:
        raise NotImplementedError()

    @abc.abstractmethod
    def delta(self, state: S, x: int) -> S:
        raise NotImplementedError()

    @abc.abstractmethod
    def is_final(self, state: S) -> bool:
        raise NotImplementedError()


class Counter(Automata[int]):
    def initial_state(self) -> int:
        return 0

    def delta(self, state: int, x: int) -> int:
        return state + x

    def is_final(self, state: int) -> bool:
        return state >= 10


class Cont(Generic[R], metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def __call__(self, automata: Automata[S]) -> R:
        raise NotImplementedError()


class EAutomata(metaclass=abc.ABCMeta):
    """
    ∃S. Automata[S]
    """

    @abc.abstractmethod
    def unpack(self, cont: Cont[R]) -> R:
        raise NotImplementedError()

    @staticmethod
    def pack(automata: Automata[S]) -> 'EAutomata':
        return EAutomataBody[S](automata)


class EAutomataBody(EAutomata, Generic[S]):
    def __init__(self, automata: Automata[S]):
        self._automata = automata

    def unpack(self, cont: Cont[R]) -> R:
        return cont(self._automata)


class Test:
    automata: EAutomata

    def __init__(self, automata: Automata[S]):
        self.automata = EAutomata.pack(automata)

    def test(self) -> bool:
        class C(Cont[bool]):
            def __call__(self, automata: Automata[S]) -> bool:
                s0 = automata.initial_state()
                # reveal_type(automata) #=> Automata[S`-1]
                # reveal_type(s0) #=> S`-1
                s1 = automata.delta(s0, 1)
                s2 = automata.delta(s1, 2)
                s3 = automata.delta(s2, 3)
                return automata.is_final(s3)
        return self.automata.unpack(C())


test = Test(Counter())
test.test()

有没有办法简化上述方法,或者有没有更好的办法在Python中使用存在类型


Tags: testselfreturndefclassintboolraise