wst*_*omv 5 python collections counter type-hinting
该名称Counter在collections(作为类)和在typing(作为泛型类型名称)中定义。不幸的是,它们略有不同。处理这个问题的推荐方法是什么?
相同点和不同点:
之后from collections import Counter,
Counter("foo")来创建一个新Counter对象;dict:issubclass(Counter, dict)返回True;Counter,例如cnt: Counter[str] = Counter("foo")raises TypeError: 'type' object is not subscriptable(类型提示失败)之后from typing import Counter,
Counter("foo")来创建一个新的Counter对象(实际上,有点出乎我的意料);dict: issubclass(Counter, dict)raises 的子类TypeError: issubclass() arg 1 must be a class;Counter,例如cnt: Counter[str] = Counter("foo")。在很多情况下 1.1 和 2.1 已经足够好了,所以导入的选择并不重要。但似乎您不能同时使用 1.3 和 2.2 进行一次导入。在后两者中,类型提示比子类检查更重要。如果你想写类型提示,那么from typing import Counter就足够了。不过,如果你写的话,我会发现它更清晰(并且更符合其他一些类型的需要)
from collections import Counter # to indicate that you want the implementation
from typing import Counter # to indicate that you want to write type hints
Run Code Online (Sandbox Code Playgroud)
(注意顺序很重要。)
如果你想拥有这一切怎么办?这些是我看到的选项:
from collections import Counter
import typing
Run Code Online (Sandbox Code Playgroud)
并使用typing.Counter实现1.3。不好看,太啰嗦了。
import collections
from typing import Counter
Run Code Online (Sandbox Code Playgroud)
并用于collections.Counter实现 2.2(如果需要;我在教学中需要它)。
from collections import Counter as counter
from typing import Counter
Run Code Online (Sandbox Code Playgroud)
并使用counter实现2.2。
from collections import Counter
from typing import Counter as Bag # or Multiset
Run Code Online (Sandbox Code Playgroud)
并在类型提示中使用Bag(或Multiset)。(但这肯定会令人困惑。)
import collections as co # to access the class
from typing import Counter # to access constructor and provide type hints
Run Code Online (Sandbox Code Playgroud)
并使用
co.Counter或Counter作为构造co.Counter作为类,如issubclass(co.Counter, dict)Counter在类型提示中使用,例如cnt: Counter[str]那么是不是也被推荐做
from typing import Deque
Run Code Online (Sandbox Code Playgroud)
并Deque用作构造函数,而不是co.deque? (我认为/希望不是。)
对于其他类型(例如defaultdictand deque),这似乎不是问题:
from collections import defaultdict, deque
from typing import DefaultDict, Deque
Run Code Online (Sandbox Code Playgroud)
给你所有。
我是否忽略了什么?
从 Python 3.9 开始,您可以执行以下操作:
from collections import Counter
c: Counter[str] = Counter()
Run Code Online (Sandbox Code Playgroud)
请参阅:https://docs.python.org/3/library/typing.html#typing.Counter
自 3.9 版起已弃用:collections.Counter 现在支持 []。请参阅 PEP 585 和通用别名类型。
可能有一些更高级的情况这不起作用,但您可以创建一个继承自两者的子类:
import typing
import collections
KT = typing.TypeVar("KT")
class Counter(collections.Counter, typing.Counter[KT]): pass
c: Counter[str] = Counter("foo")
print(isinstance(c, dict)) # True
Run Code Online (Sandbox Code Playgroud)