python - 创建或 isinstance 的 Python 泛型检查其类型参数
问题描述
我想创建一个可以用类型参数化的可继承类。这是一个没有类型注释的工作示例:
class Simple:
pass
class Bla:
obj_class = Simple
def do(self):
return self.obj_class()
def check(self, x):
return isinstance(x, self.obj_class)
此代码的用户将从 Bla 继承,并且可以设置不同的 obj_class,如下所示:
class Advanced(Simple):
pass
class Foo(Bla):
obj_class = Advanced
当我想正确输入注释时,问题就开始了。我想让 Bla 从 Generic[T] 继承,其中 T 定义为TypeVar('T', bound=Simple)
,但是构造函数 T() 和 isinstance 将不起作用,并且手动为 obj_class 分配不同的类也不起作用。
这是一个无效的示例,因为 T 不能在非键入上下文中使用:
class Simple:
pass
T = TypeVar('T', bound=Simple)
class Bla(Generic[T]):
def do(self) -> T:
return T()
def check(self, x: Any) -> bool:
return isinstance(x, T)
这是另一个不起作用的示例,由于类型不兼容,我无法将 Simple 分配给 obj_class。
class Simple:
pass
T = TypeVar('T', bound=Simple)
class Bla(Generic[T]):
obj_class: Type[T] = Simple
def do(self) -> T:
return self.obj_class()
def check(self, x: Any) -> bool:
return isinstance(x, self.obj_class)
class Advanced(Simple):
pass
class Foo(Bla):
obj_class = Advanced
有没有办法解决这个问题?
解决方案
你不需要Type[T] = Simple
。
mypy 状态:
赋值中的类型不兼容(表达式的类型为“Type[Simple]”,变量的类型为“Type[T]”)。
您正在尝试将具体类型分配给泛型类型变量。
相反,请执行以下操作:
class Simple:
pass
class Advanced(Simple):
pass
class Other:
pass
T = TypeVar('T', bound=Simple)
class Bla(Generic[T]):
obj_class: Type[T]
def do(self) -> T:
return self.obj_class()
def check(self, x: Any) -> bool:
return isinstance(x, self.obj_class)
class SimpleFoo(Bla[Simple]):
obj_class = Simple
class AdvancedFoo(Bla[Advanced]):
obj_class = Advanced
class OtherFoo(Bla[Other]):
obj_class = Other
现在,mypy 正确地指出:
错误:“Bla”的类型参数“tmp.Other”必须是“tmp.Simple”的子类型
笔记
OtherFoo
必须Bla
使用特定类型进行子类化,以便 mypy 正确警告您。
以下不会产生错误:
class OtherFoo(Bla):
obj_class = Other
推荐阅读
- cypress - 使用 Cypress 从自定义命令或插件调度操作
- react-native - 如何在本机反应中接收推送通知时绕过请勿打扰(DND)模式?
- python - 如何从 pyspark 中的 spark 数据框中提取特定值?
- mongodb - 覆盖 Mongo 源连接器
- liquid - 提取最后两个斜杠之间的字符串
- django - Django Crispy Forms 不显示第一个文本字段
- html - https://localhost:5001/api/contacts 的 Http 失败响应:405 OK
- c - OpenSSL 111 API 解密密码
- angular - 如何将 Angular 部署到 Firebase 托管
- python - 几何不被识别为 Find_SRID 的参数