我正在尝试为类型之间的转换实现一个接口,但由于typing.Type
是协变的,所以我正在努力使其保持一致
from typing import Protocol, Type, TypeVar
from abc import abstractmethod
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
的所有子类都应实现一个带有有效签名的构造函数,以像这样进行实例化。我的用例有所不同,因为我可能不构造新类型,而只是返回一个预先存在的类型。说我愿意
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)
RHS很好,因为mypy cos
Type
是协变的,但很明显,API已损坏,因为X
不是XX
。如果Type
不是协变的,则不必担心:在Wrapper
更新为支持XX
之前,RHS不会进行类型检查。
我的问题是:鉴于Type
的协方差,是否有某种方法可以实现这一目标(或类似的目标?)>
Context
我想用它来将一个类型转换为多种其他类型,显式地指定所需的类型,而不仅仅是into_X
,into_Y
等。我希望使用TypeVar
或overload
来做到这一点。我也遇到了困难there。
这受rust的Into
启发,其中t: Type[U]
是类型参数,而不是函数参数。
我正在尝试为类型之间的转换实现一个接口,但是我一直在努力使之保持一致,因为键入。Type与键入import Protocol,Type,来自abc import的TypeVar是协变的...
eval
解决了这个问题。class Wrapper:
def __init__(self, x: X):
self._x = x
def into(self, t: Type[X]) -> X:
return eval(f'{t}({self._x})')