我为ordered-set库提供了contributed类型提示。问题是,尽管我在ordered_set.pyi文件中有以下几行:
from typing import MutableSet, TypeVar, Sequence
T = TypeVar('T')
class OrderedSet(MutableSet[T], Sequence[T]):
...我不能写:
IntOrderedSet = OrderedSet[int]在我的代码中,Python引发了:
TypeError: 'ABCMeta' object is not subscriptable之所以会发生这种情况,是因为在ordered_set.py中OrderedSet被定义为:
from collections.abc import MutableSet, Sequence
class OrderedSet(MutableSet, Sequence):
...我提交了一个PR,更改了OrderedSet类的to inherit from typing classes,但ordered-set的所有者拒绝接受它,因为他说:
在代码中导入类型会在代码中添加安装时依赖项和运行时开销。ordered_set作为一个独立的模块已经存在6年了。有些人可能决定他们不想使用setuptools,只需将ordered_set放在他们的PYTHONPATH上,它仍然可以工作。我不想因为类型而失去这一点。
有没有一种方法可以在不修改库ordered_set.py文件的情况下支持类似OrderedSet[int]的类型?
发布于 2018-09-30 00:36:28
据我所知,唯一的解决办法是定义任何自定义类型别名,使其仅在类型检查时存在,而不是在运行时存在。
要做到这一点,您需要:
if typing.TYPE_CHECKING:块中定义任何类型别名。from __future__ import annotations,它会自动执行此操作。也就是说,避免从一开始就必须计算类型提示。例如,在您的特定设置中,您可以在某个地方为OrderedSet库贡献存根,然后编写如下代码(假设Python 3.7+):
from __future__ import annotations
from typing import TYPE_CHECKING
from ordered_set import OrderedSet
# Basically equivalent to `if False`
if TYPE_CHECKING:
IntOrderedSet = OrderedSet[Int]
def expects_int_ordered_set(x: IntOrderedSet) -> None:
# blah
some_ordered_set: IntOrderedSet = OrderedSet()或者,如果您使用的是Python 3.6或更低版本:
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_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之类的类型检查器可能会根据我们最终如何使用该变量自动推断出正确的类型。
https://stackoverflow.com/questions/52569356
复制相似问题