首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何处理名称冲突collections.Counter和typing.Counter?

如何处理名称冲突collections.Counter和typing.Counter?
EN

Stack Overflow用户
提问于 2020-05-01 21:29:44
回答 3查看 940关注 0票数 7

名称Counter是在collections (作为类)和typing (作为泛型类型名称)中定义的。不幸的是,它们略有不同。建议的处理方法是什么?

异同点:

  1. After from collections import Counter

代码语言:javascript
复制
1. you can call the constructor `Counter("foo")` to create a fresh `Counter` object;
2. you can verify that it is subclass of `dict`: `issubclass(Counter, dict)` returns `True`;
3. you cannot use it to declare a specific variant of `Counter`, e.g. `cnt: Counter[str] = Counter("foo")` raises `TypeError: 'type' object is not subscriptable` (the type hint fails)

  1. After from typing import Counter

代码语言:javascript
复制
1. you can call the constructor `Counter("foo")` to create a fresh `Counter` object (actually, somewhat to my surprise);
2. you cannot use it to verify that it is subclass of `dict`: `issubclass(Counter, dict)` raises `TypeError: issubclass() arg 1 must be a class`;
3. you can declare a specific variant of `Counter`, e.g. `cnt: Counter[str] = Counter("foo")`.

在许多情况下,1.1和2.1已经足够好了,所以导入的选择并不重要。但是,似乎不能同时使用1.3和2.2来处理单个导入。在后两者中,类型提示比子类检查更重要。如果您想编写类型提示,那么from typing import Counter就足够了。不过,如果您编写的话,我会发现它更清晰(更符合其他类型所需的内容)

代码语言:javascript
复制
from collections import Counter  # to indicate that you want the implementation
from typing import Counter  # to indicate that you want to write type hints

(注意该命令是重要的。)。

如果你想拥有一切呢?以下是我看到的选择:

  1. Do

代码语言:javascript
复制
from collections import Counter
import typing

并利用typing.Counter实现了1.3分。不太好,太冗长了。

  1. Do

代码语言:javascript
复制
import collections
from typing import Counter

并使用collections.Counter实现2.2 (如果需要的话,我在教学中需要它)。

  1. Do

代码语言:javascript
复制
from collections import Counter as counter
from typing import Counter

并利用counter实现了2.2。

  1. Do

代码语言:javascript
复制
from collections import Counter
from typing import Counter as Bag  # or Multiset

并在提示类型中使用Bag (或Multiset)。(但这肯定会让人困惑。)

  1. Do (如评论中所建议)

代码语言:javascript
复制
import collections as co  # to access the class
from typing import Counter  # to access constructor and provide type hints

并使用

作为类的constructor

  • use co.CounterCounter,例如类型提示中的issubclass(co.Counter, dict)

  • use Counter,例如cnt: Counter[str]

那么,是否也建议这样做呢?

代码语言:javascript
复制
from typing import Deque

并使用Deque作为构造函数,而不是使用co.deque?(我想/希望不是。)

对于其他类型(如defaultdictdeque),这似乎不是一个问题:

代码语言:javascript
复制
from collections import defaultdict, deque
from typing import DefaultDict, Deque

给你们所有人。

我是不是忽略了什么?

EN

回答 3

Stack Overflow用户

发布于 2021-12-24 17:17:58

从Python3.9开始,您可以:

代码语言:javascript
复制
from collections import Counter

c: Counter[str] = Counter()

请参阅:https://docs.python.org/3/library/typing.html#typing.Counter

自3.9版以来,

就不再受欢迎了: collections.Counter现在支持[]。参见PEP 585和通用别名类型.

票数 1
EN

Stack Overflow用户

发布于 2020-05-01 21:41:44

可能有一些更高级的情况下,这是行不通的,但您可以创建一个子类,从这两个子类继承:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2020-05-01 22:25:08

最少的痛苦可能是满足于基于字符串的类型暗示。然而,并不是每个IDE都会解释它;PyCharm在这段代码段的最后一行检测到类型不匹配,而VSCode认为一切都很好。

代码语言:javascript
复制
from collections import Counter

mycounter: 'Counter[str]' = Counter('foo')

def func1(counter: 'Counter[str]'):
    pass

def func2(counter: 'Counter[int]'):
    pass

func1(mycounter)
func2(mycounter)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61551094

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档