Search code examples
pythonmypypython-typingpython-3.10

What is the right mypy annotation for collections.Counter?


My Problem

I am writing a Python function with a Counter that counts strings and prints the total number of strings counted. I tried annotating the function in various ways. but all failed the mypy test:

Code

from collections import Counter
import typing

def f1(c : Counter[str]) -> None:
    print(c.total())

def f2(c : Counter) -> None:
    print(c.total())

def f3(c : Counter[str, int]) -> None:
    print(c.total())


c : Counter = Counter()
c.update(['a', 'b', 'c', 'a', 'b', 'c'])

f1(c)
f2(c)
f3(c)

Errors

use_counter.py:5: error: "Counter[str]" has no attribute "total"
use_counter.py:8: error: "Counter[Any]" has no attribute "total"
use_counter.py:10: error: "Counter" expects 1 type argument, but 2 given
use_counter.py:11: error: "Counter[Any]" has no attribute "total"

What Have I Tried

Various ways to annotate Counter (in f1, f2, and f3) and googling for answers.

My Question

What's the right way to annotate a collections.Counter so that its methods (like total) are recognized by mypy?


Solution

  • Counter.total was added to mypy in version 0.940. Your code, part f1 and f2 works fine

    from collections import Counter
    
    
    def f1(c: Counter[str]) -> None:
        print(c.total())
    
    
    def f2(c: Counter) -> None:
        print(c.total())
    
    
    c: Counter = Counter()
    c.update(["a", "b", "c", "a", "b", "c"])
    
    f1(c)
    f2(c)