Имя Counter
определяется как в collections
(как класс), так и в typing
(как универсальное c имя типа). К сожалению, они немного отличаются. Каков рекомендуемый способ борьбы с этим?
Сходства и различия:
После from collections import Counter
,
- вы можете позвонить конструктор
Counter("foo")
для создания объекта fre sh Counter
; - вы можете убедиться, что он является подклассом
dict
: issubclass(Counter, dict)
возвращает True
; - , который вы не можете используйте его для объявления определенного c варианта
Counter
, например, cnt: Counter[str] = Counter("foo")
повышает TypeError: 'type' object is not subscriptable
(подсказка типа не выполняется)
После from typing import Counter
,
- Вы можете вызвать конструктор
Counter("foo")
для создания объекта fre sh Counter
(на самом деле, к моему удивлению); - вы не можете использовать его, чтобы убедиться, что он является подклассом
dict
: issubclass(Counter, dict)
повышает TypeError: issubclass() arg 1 must be a class
; - Вы можете объявить определенный c вариант
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
(Обратите внимание, что порядок имеет значение.)
Что если вы хотите все это иметь? Вот варианты, которые я вижу:
- Do
from collections import Counter
import typing
и использование typing.Counter
для достижения 1,3. Не красиво, слишком многословно.
Выполните
import collections
from typing import Counter
и используйте collections.Counter
для достижения 2,2 (при необходимости; мне это нужно было в обучении).
Do
from collections import Counter as counter
from typing import Counter
и использование counter
для достижения 2.2.
Do
from collections import Counter
from typing import Counter as Bag # or Multiset
и используйте Bag
(или Multiset
) в подсказках типа. (Но это непонятно.)
Выполните (как указано в комментарии)
import collections as co # to access the class
from typing import Counter # to access constructor and provide type hints
и используйте
- либо
co.Counter
или Counter
в качестве конструктора - используйте
co.Counter
в качестве класса, например, issubclass(co.Counter, dict)
- используйте
Counter
в подсказках типа, например, cnt: Counter[str]
Это также рекомендуется сделать
from typing import Deque
и использовать Deque
в качестве конструктора, а не co.deque
? (Я бы подумал / надеюсь, что нет.)
Для других типов (таких как defaultdict
и deque
) это, похоже, не проблема:
from collections import defaultdict, deque
from typing import DefaultDict, Deque
дает вам все.
Я что-то пропускаю?