python - 是否可以在 Python 中将通用 C[T] 静态类型为 T ?
问题描述
我正在使用 SQLite,其中类型提示仍然远非完美,我最终得到了一个我认为我想做的 MCVE,它可能与静态类型的 ABC 有关。
例子:
T = TypeVar('T')
class ColumnarValue(Generic[T]):
pass
def test1(guard: ColumnarValue[str]): ...
def test2(guard: ColumnarValue[int]): ...
# These should work
test1("Hello")
test2(42)
# These should be type errors
test1(42)
test2("Hello")
# Or, likewise:
test_assignment_1: ColumnarValue[str] = "this line should typecheck"
test_assignment_2: ColumnarValue[int] = "this line should NOT typecheck"
我尝试使用 ABC,但由于它们似乎使用 ABC.register() 进行注册,因此类型检查器不知道我在说什么。
我也尝试过通用协议,但我必须设计一个协议来保护每种类型 T 所期望的功能。
我正在使用 Pyright/Pylance 对此进行测试,但如果这是问题的一部分,则可以将替代方案视为答案。
我还发现https://github.com/antonagestam/phantom-types根据文档,“不会增加任何处理或内存开销”。这并不完全正确,因为它们__instancecheck__
在运行时通过 .parse 和协议(尽管它们在技术上不会创建任何新对象,但它们在堆栈帧中确实有一些开销)。
唉,这不是一个静态检查器,虽然那里的解决方案似乎用来assert isinstance("hello", MyStr)
确保类型检查器可以在该行之后满足此类保证(这至少在 mypy 和 pylance 中有效),但它不会触发任何类型检查时间错误与assert isinstance("hello", MyInt)
. 该代码将在运行时使断言失败。
最终,我希望能够拥有一个T
可以调用的类型,C[T]
这样当我col_name = Column(String, ...)
在模型中声明 a 时,我就可以col_name = "value"
对其进行静态检查或对其进行一些变体。
这可能吗?如果是,那么魔法在哪里?
解决方案
如果最终要将这些列放入模型类中,则可以使用描述符property
(如果您熟悉的话,这就是装饰器在后台使用的内容)。
粗略的草图:
from typing import TypeVar, Generic, Any
T = TypeVar("T")
class ColumnarValue(Generic[T]):
def __get__(self, instance: object, owner: Any) -> T:
...
def __set__(self, instance: object, value: T) -> None:
...
class Model:
some_str_column: ColumnarValue[str]
some_int_column: ColumnarValue[int]
m = Model()
m.some_str_column = "this line typechecks"
m.some_int_column = "this line does NOT typecheck"
推荐阅读
- anaconda - 如何防止 Anaconda 'conda update --all' 降级我的 Tensorflow 安装
- list - 在未排序的数字数组中查找具有给定总和的所有对
- java - 如何找到 java 的方法是如何写在 itellj 上的?
- authentication - 具有 okta 身份验证的 Nodejs 应用程序将“X-Frame-Options”抛出到“sameorigin”错误和状态不匹配错误
- php - VS Code - 编程语言文档的快捷方式
- java - 使用 LDAP 的 Spring Security - 登录后出错
- amazon-web-services - 无法在通过 Zappa(lambda) 托管的 django 应用程序上通过 SES 发送电子邮件
- java - 如何使用 AST 从 Java 方法中提取元数据?
- javascript - webpack-dev-server 没有重新编译输出文件
- python - 过滤后在 Pandas 数据框中获取 KeyError