[英]Provide OrderedSet[int] like types using stub file without modifying ordered-set library
I've contributed type hints for ordered-set library. 我为有序集库提供了类型提示。 The problem is that despite I have the following lines in
ordered_set.pyi
file: 问题是尽管我在
ordered_set.pyi
文件中有以下几行:
from typing import MutableSet, TypeVar, Sequence
T = TypeVar('T')
class OrderedSet(MutableSet[T], Sequence[T]):
...
I cannot write: 我不能写:
IntOrderedSet = OrderedSet[int]
in my code, Python raises: 在我的代码中,Python提出:
TypeError: 'ABCMeta' object is not subscriptable
It happens because in the ordered_set.py
OrderedSet
is defined as: 它发生的原因是在
ordered_set.py
OrderedSet
定义为:
from collections.abc import MutableSet, Sequence
class OrderedSet(MutableSet, Sequence):
...
I made a PR with commit that changes OrderedSet
class to inherit from typing classes , but ordered-set
owner refused to accept it, because as he said: 我做了一个带有提交的PR,它改变了
OrderedSet
类来继承输入类 ,但是ordered-set
所有者拒绝接受它,因为他说:
Importing typing inside the code adds an install-time dependency and a run-time cost to the code.
在代码中导入键入会为代码添加安装时依赖性和运行时成本。 ordered_set has gotten by as a single module with no dependencies for 6 years.
ordered_set作为单个模块获得了6年没有依赖关系。 Someone could decide they want nothing to do with setuptools and just drop ordered_set on their PYTHONPATH, and it would still work.
有人可以决定他们不想与setuptools做任何事情,只是在他们的PYTHONPATH上删除ordered_set,它仍然可以工作。 I'd hate to lose that over types.
我不想失去那种类型。
Is there a way, to support OrderedSet[int]
like types without modifying the library ordered_set.py
file? 有没有办法,在不修改库
ordered_set.py
文件的情况下支持OrderedSet[int]
类型?
The only workaround that I'm aware of is to define any custom type aliases such that they exist only at type-check time, and never at run-time. 我所知道的唯一解决方法是定义任何自定义类型别名,使它们仅在类型检查时存在,而不是在运行时存在。
In order to do this, you would need to: 为此,您需要:
if typing.TYPE_CHECKING:
blocks. if typing.TYPE_CHECKING:
blocks,则在里面定义任何类型的别名。 The typing.TYPE_CHECKING
block is always false at runtime, and treated as being true by type checkers. typing.TYPE_CHECKING
块在运行时始终为false,并通过类型检查器视为true。 from __future__ import annotations
, which does that automatically. from __future__ import annotations
,这会自动执行此操作。 That is, avoid having to ever evaluate type hints in the first place. So for example, in your specific setup, you could contribute stubs for the OrderedSet library somewhere then write your code to look like this (assume Python 3.7+): 例如,在您的特定设置中,您可以在某处为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()
Or, if you're using Python 3.6 or lower: 或者,如果您使用的是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()
If you're ok with lying a little, we could dispense with the string stuff and define IntOrderedSet
to be slightly different things at type-checking time vs runtime. 如果你可以稍微说谎,我们可以省去字符串的东西,并在类型检查时间和运行时定义
IntOrderedSet
略有不同。 For example: 例如:
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()
Make sure to be careful when you're doing this though -- the type checker won't check anything in the 'else' block/won't check to make sure whatever you're doing there is consistent with what's in the if TYPE_CHECKING
block. 确保在你这样做时要小心 - 类型检查器不会检查'else'块中的任何内容/不会检查以确保你所做的任何事情与
if TYPE_CHECKING
中的内容if TYPE_CHECKING
块。
The final solution would be to just not define an IntOrderedSet
type in the first place. 最终的解决方案是首先不要定义
IntOrderedSet
类型。 This lets us skip hack 1 while only needing to use hack 2 (which isn't so much a hack -- it'll be default behavior in Python in a few years). 这让我们跳过hack 1而只需要使用hack 2(这不是一个黑客攻击 - 它将在几年内成为Python中的默认行为)。
So for example, we could do this: 例如,我们可以这样做:
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()
Depending on context, it may be the case that I don't even need to add an annotation to that last variable declaration. 根据上下文,可能是我甚至不需要为最后一个变量声明添加注释。 Here, we do, but if we were defining that variable inside of a function, it's possible type checkers like mypy would automatically infer the correct type for us based on how we end up using that variable.
在这里,我们这样做,但如果我们在函数内部定义该变量,那么像mypy这样的类型检查器会根据我们最终使用该变量的方式自动推断出正确的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.