提问人:joel 提问时间:10/12/2019 最后编辑:joel 更新时间:5/17/2020 访问量:229
“输入”和“从”接口:在打字方面苦苦挣扎。类型的协方差
Into and From interfaces: struggling with typing.Type's covariance
问:
我正在尝试实现一个用于类型之间转换的接口,但我正在努力使其保持一致,因为是协变的typing.Type
U = TypeVar('U')
class Into(Protocol[U]):
@abstractmethod
def into(self, t: Type[U]) -> U:
pass
这些文档给出了一个类似的例子,但有一个关键的区别
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)
mypy 的 RHS 很好,因为 cos 是协变的,但显然 API 已损坏,因为 an 不是 .如果不是协变,这不会是一个问题:RHS 不会进行类型检查,直到更新为支持 .Type
X
XX
Type
Wrapper
XX
我的问题是:有没有办法实现这一点(或类似的东西),给定的协方差?Type
上下文
我想用它来将一个类型转换为多个其他类型,显式指定所需的类型,而不仅仅是 ,等等。我希望用 or 来做到这一点。我在那里也遇到了困难。into_X
into_Y
TypeVar
overload
这是受 rust 的启发,其中是类型参数而不是函数参数。Into
t: Type[U]
答:
-2赞
Kate Melnykova
5/17/2020
#1
eval
解决了问题。
class Wrapper:
def __init__(self, x: X):
self._x = x
def into(self, t: Type[X]) -> X:
return eval(f'{t}({self._x})')
评论
1赞
chepner
5/17/2020
你根本不需要; 会做同样的事情(假设可以用来首先使 ,或者更确切地说是 的结果)。eval
return t(self._x)
t
t
self._x
str(self._x)
0赞
Kate Melnykova
5/17/2020
我以为这是一个字符串。t
1赞
joel
5/17/2020
t
不会是字符串。它是一种类型,例如如果是,将是self._x
1
t
int
0赞
Kate Melnykova
5/17/2020
我的解决方案仍然有效,@chepner的解决方案更简单,也有效。我认为问题已经解决。
0赞
joel
5/17/2020
正如 Chepner 所指出的,这只有在你能从另一个类似中构造一个时才有效,而这通常不能,你不能X
X
X(x)
评论
into
根本没有使用它的参数,所以继承或协方差不是你的问题。t
Into[X]
Into[Y]
Wrapper()
Wrapper
w.into(int)
w
w
w.into(List[str])
w.into(List[int])
X
mypy
into