在打字上挣扎.Type的协方差

时间:2019-10-12 13:30:05

标签: python covariance type-hinting

我正在尝试为类型之间的转换实现一个接口,但由于typing.Type是协变的,因此我正在努力使其保持一致

U = TypeVar('U')


class Into(Protocol[U]):
    @abstractmethod
    def into(self, t: Type[U]) -> U:
        pass

docs给出了一个相似的示例,但有一个关键的区别

class User: ...
class BasicUser(User): ...
class ProUser(User): ...
class TeamUser(User): ...

def make_new_user(user_class: Type[User]) -> User:
    return user_class()

他们说类型检查器应检查User的所有子类应实现带有有效签名的构造函数,以使其实例化。我的用例是不同的cos,我可能不会构造新的类型,而只是返回一个预先存在的类型。说我做

class X: pass

class Wrapper:
    def __init__(self, x: X):
        self._x = x

    def into(self, t: Type[X]) -> X:
        return self._x

一切正常,直到有人继承X

w = Wrapper(X)
...
class XX(X): pass
x: XX = w.into(XX)

mypy cos Type是协变的,因此RHS很好,但是显然X不是XX的API已损坏cos。如果Type不是协变的,则不必担心:在更新Wrapper以支持XX之前,RHS不会键入check。

我的问题是:鉴于Type的协方差,是否有某种方法可以实现这一目标(或类似方法)?

上下文

我想用它来将一个类型转换为多种其他类型,显式地指定所需的类型,而不仅仅是into_Xinto_Y等。我希望使用TypeVaroverload。我也遇到了问题there

这受rust的Into的启发,其中t: Type[U]是类型参数,而不是函数参数。

1 个答案:

答案 0 :(得分:-2)

eval解决了这个问题。

class Wrapper:
    def __init__(self, x: X):
        self._x = x

    def into(self, t: Type[X]) -> X:
        return eval(f'{t}({self._x})')