Python 使用存根文件提供OrderedSet[int]类类型,而不修改OrderedSet库
我已经输入了库的提示。问题是,尽管我在Python 使用存根文件提供OrderedSet[int]类类型,而不修改OrderedSet库,python,python-3.x,type-hinting,typehints,ordered-set,Python,Python 3.x,Type Hinting,Typehints,Ordered Set,我已经输入了库的提示。问题是,尽管我在ordered_set.pyi文件中有以下几行代码: 输入import MutableSet、TypeVar、Sequence T=TypeVar('T') 类OrderedSet(可变表集[T],序列[T]): ... 我不能写: IntOrderedSet=OrderedSet[int] 在我的代码中,Python提出: TypeError:“ABCMeta”对象不可下标 发生这种情况是因为在ordered_set.pyordered set中定义
ordered_set.pyi
文件中有以下几行代码:
输入import MutableSet、TypeVar、Sequence
T=TypeVar('T')
类OrderedSet(可变表集[T],序列[T]):
...
我不能写:
IntOrderedSet=OrderedSet[int]
在我的代码中,Python提出:
TypeError:“ABCMeta”对象不可下标
发生这种情况是因为在ordered_set.py
ordered set
中定义为:
from collections.abc导入可变表集,序列
类OrderedSet(可变表集,序列):
...
我用commit做了一个PR,更改了OrderedSet
类,但是OrderedSet
所有者拒绝接受它,因为正如他所说:
在代码中输入类型会为代码添加安装时依赖项和运行时成本。ordered_set作为一个单一模块已经使用了6年,没有任何依赖关系。有些人可能决定不想与setuptools有任何关系,只需在他们的PYTHONPATH上删除ordered_set,它仍然可以工作。我不想因为类型而失去这一点
有没有一种方法可以在不修改库
OrderedSet.py
文件的情况下支持类似于OrderedSet[int]
的类型 我知道的唯一解决方法是定义任何自定义类型别名,使它们仅在类型检查时存在,而不在运行时存在
为此,您需要:
中定义任何类型别名。键入\u检查:
块。typing.TYPE_CHECKING
块在运行时始终为false,并被类型检查器视为true,这会自动完成。也就是说,首先要避免计算类型提示
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
def expects_int_ordered_set(x: 'IntOrderedSet') -> None:
# blah
some_ordered_set: 'IntOrderedSet' = OrderedSet()
如果你可以稍微撒谎,我们可以省去字符串的东西,将IntOrderedSet
定义为在类型检查时间和运行时略有不同的东西。例如:
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
else:
IntOrderedSet = OrderedSet
def expects_int_ordered_set(x: IntOrderedSet) -> None:
# blah
some_ordered_set = IntOrderedSet()
但是,在执行此操作时请务必小心--类型检查器不会检查“else”块中的任何内容/不会检查以确保您在那里执行的任何操作与if type\u CHECKING
块中的内容一致
最终的解决方案是不首先定义IntOrderedSet
类型。这让我们可以跳过hack 1,而只需要使用hack 2(这不是什么hack,几年后它将成为Python中的默认行为)
例如,我们可以这样做:
from __future__ import annotations
from ordered_set import OrderedSet
def expects_int_ordered_set(x: OrderedSet[int]) -> None:
# blah
some_ordered_set: OrderedSet[int] = OrderedSet()
根据上下文的不同,可能我甚至不需要在最后一个变量声明中添加注释。在这里,我们是这样做的,但如果我们在函数中定义该变量,那么像mypy这样的类型检查器可能会根据我们最终使用该变量的方式自动推断出正确的类型。谢谢!我不知道这两个黑客。工作起来很有魅力。
from __future__ import annotations
from ordered_set import OrderedSet
def expects_int_ordered_set(x: OrderedSet[int]) -> None:
# blah
some_ordered_set: OrderedSet[int] = OrderedSet()