Как сделать счетчик в python
The counter is a container included in the collections module. Now you all must be wondering what is a container. Don’t worry first let’s discuss the container.
What is Container?
Containers are objects that hold objects. They provide a way to access the contained objects and iterate over them. Examples of built-in containers are Tuples, lists, and dictionaries. Others are included in the Collections module.
A Counter is a subclass of dict. Therefore it is an unordered collection where elements and their respective count are stored as a dictionary. This is equivalent to a bag or multiset of other languages.
Syntax
Initialization:
The constructor of the counter can be called in any one of the following ways:
Как сделать функцию-счетчик?
![]()
Без использования глобальных переменных (вместо этого используем замыкание):
С помощью вызова create_counter() можно создать сколько угодно функций-счетчиков, каждая будет работать независимо от другой.
![]()
Если функция должна запоминать внутри себя состояние, то лучше это делать не через функции, а через классы:
Впрочем, для вашего случая можно использовать и функцию-генератор. Но тогда обращаться к такому счётчику нужно будет не через вызов, а через протокол итерации:
Причём для простого инкрементного счётчика уже есть готовая функция в стандартной библиотеке, так что можно не писать её самостоятельно, а взять готовую:
collections — Container datatypes¶
This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict , list , set , and tuple .
factory function for creating tuple subclasses with named fields
list-like container with fast appends and pops on either end
dict-like class for creating a single view of multiple mappings
dict subclass for counting hashable objects
dict subclass that remembers the order entries were added
dict subclass that calls a factory function to supply missing values
wrapper around dictionary objects for easier dict subclassing
wrapper around list objects for easier list subclassing
wrapper around string objects for easier string subclassing
ChainMap objects¶
New in version 3.3.
A ChainMap class is provided for quickly linking a number of mappings so they can be treated as a single unit. It is often much faster than creating a new dictionary and running multiple update() calls.
The class can be used to simulate nested scopes and is useful in templating.
class collections. ChainMap ( * maps ) ¶
A ChainMap groups multiple dicts or other mappings together to create a single, updateable view. If no maps are specified, a single empty dictionary is provided so that a new chain always has at least one mapping.
The underlying mappings are stored in a list. That list is public and can be accessed or updated using the maps attribute. There is no other state.
Lookups search the underlying mappings successively until a key is found. In contrast, writes, updates, and deletions only operate on the first mapping.
A ChainMap incorporates the underlying mappings by reference. So, if one of the underlying mappings gets updated, those changes will be reflected in ChainMap .
All of the usual dictionary methods are supported. In addition, there is a maps attribute, a method for creating new subcontexts, and a property for accessing all but the first mapping:
A user updateable list of mappings. The list is ordered from first-searched to last-searched. It is the only stored state and can be modified to change which mappings are searched. The list should always contain at least one mapping.
new_child ( m = None , ** kwargs ) ¶
Returns a new ChainMap containing a new map followed by all of the maps in the current instance. If m is specified, it becomes the new map at the front of the list of mappings; if not specified, an empty dict is used, so that a call to d.new_child() is equivalent to: ChainMap(<>, *d.maps) . If any keyword arguments are specified, they update passed map or new empty dict. This method is used for creating subcontexts that can be updated without altering values in any of the parent mappings.
Changed in version 3.4: The optional m parameter was added.
Changed in version 3.10: Keyword arguments support was added.
Property returning a new ChainMap containing all of the maps in the current instance except the first one. This is useful for skipping the first map in the search. Use cases are similar to those for the nonlocal keyword used in nested scopes . The use cases also parallel those for the built-in super() function. A reference to d.parents is equivalent to: ChainMap(*d.maps[1:]) .
Note, the iteration order of a ChainMap() is determined by scanning the mappings last to first:
This gives the same ordering as a series of dict.update() calls starting with the last mapping:
Changed in version 3.9: Added support for | and |= operators, specified in PEP 584.
The MultiContext class in the Enthought CodeTools package has options to support writing to any mapping in the chain.
Django’s Context class for templating is a read-only chain of mappings. It also features pushing and popping of contexts similar to the new_child() method and the parents property.
The Nested Contexts recipe has options to control whether writes and other mutations apply only to the first mapping or to any mapping in the chain.
ChainMap Examples and Recipes¶
This section shows various approaches to working with chained maps.
Example of simulating Python’s internal lookup chain:
Example of letting user specified command-line arguments take precedence over environment variables which in turn take precedence over default values:
Example patterns for using the ChainMap class to simulate nested contexts:
The ChainMap class only makes updates (writes and deletions) to the first mapping in the chain while lookups will search the full chain. However, if deep writes and deletions are desired, it is easy to make a subclass that updates keys found deeper in the chain:
Counter objects¶
A counter tool is provided to support convenient and rapid tallies. For example:
A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts. The Counter class is similar to bags or multisets in other languages.
Elements are counted from an iterable or initialized from another mapping (or counter):
Counter objects have a dictionary interface except that they return a zero count for missing items instead of raising a KeyError :
Setting a count to zero does not remove an element from a counter. Use del to remove it entirely:
New in version 3.1.
Changed in version 3.7: As a dict subclass, Counter inherited the capability to remember insertion order. Math operations on Counter objects also preserve order. Results are ordered according to when an element is first encountered in the left operand and then by the order encountered in the right operand.
Counter objects support additional methods beyond those available for all dictionaries:
Return an iterator over elements repeating each as many times as its count. Elements are returned in the order first encountered. If an element’s count is less than one, elements() will ignore it.
Return a list of the n most common elements and their counts from the most common to the least. If n is omitted or None , most_common() returns all elements in the counter. Elements with equal counts are ordered in the order first encountered:
Elements are subtracted from an iterable or from another mapping (or counter). Like dict.update() but subtracts counts instead of replacing them. Both inputs and outputs may be zero or negative.
New in version 3.2.
Compute the sum of the counts.
New in version 3.10.
The usual dictionary methods are available for Counter objects except for two which work differently for counters.
This class method is not implemented for Counter objects.
Elements are counted from an iterable or added-in from another mapping (or counter). Like dict.update() but adds counts instead of replacing them. Also, the iterable is expected to be a sequence of elements, not a sequence of (key, value) pairs.
Counters support rich comparison operators for equality, subset, and superset relationships: == , != , < , <= , > , >= . All of those tests treat missing elements as having zero counts so that Counter(a=1) == Counter(a=1, b=0) returns true.
New in version 3.10: Rich comparison operations were added.
Changed in version 3.10: In equality tests, missing elements are treated as having zero counts. Formerly, Counter(a=3) and Counter(a=3, b=0) were considered distinct.
Common patterns for working with Counter objects:
Several mathematical operations are provided for combining Counter objects to produce multisets (counters that have counts greater than zero). Addition and subtraction combine counters by adding or subtracting the counts of corresponding elements. Intersection and union return the minimum and maximum of corresponding counts. Equality and inclusion compare corresponding counts. Each operation can accept inputs with signed counts, but the output will exclude results with counts of zero or less.
Unary addition and subtraction are shortcuts for adding an empty counter or subtracting from an empty counter.
New in version 3.3: Added support for unary plus, unary minus, and in-place multiset operations.
Counters were primarily designed to work with positive integers to represent running counts; however, care was taken to not unnecessarily preclude use cases needing other types or negative values. To help with those use cases, this section documents the minimum range and type restrictions.
The Counter class itself is a dictionary subclass with no restrictions on its keys and values. The values are intended to be numbers representing counts, but you could store anything in the value field.
The most_common() method requires only that the values be orderable.
For in-place operations such as c[key] += 1 , the value type need only support addition and subtraction. So fractions, floats, and decimals would work and negative values are supported. The same is also true for update() and subtract() which allow negative and zero values for both inputs and outputs.
The multiset methods are designed only for use cases with positive values. The inputs may be negative or zero, but only outputs with positive values are created. There are no type restrictions, but the value type needs to support addition, subtraction, and comparison.
The elements() method requires integer counts. It ignores zero and negative counts.
Wikipedia entry for Multisets.
C++ multisets tutorial with examples.
For mathematical operations on multisets and their use cases, see Knuth, Donald. The Art of Computer Programming Volume II, Section 4.6.3, Exercise 19.
To enumerate all distinct multisets of a given size over a given set of elements, see itertools.combinations_with_replacement() :
deque objects¶
Returns a new deque object initialized left-to-right (using append() ) with data from iterable. If iterable is not specified, the new deque is empty.
Deques are a generalization of stacks and queues (the name is pronounced “deck” and is short for “double-ended queue”). Deques support thread-safe, memory efficient appends and pops from either side of the deque with approximately the same O(1) performance in either direction.
Though list objects support similar operations, they are optimized for fast fixed-length operations and incur O(n) memory movement costs for pop(0) and insert(0, v) operations which change both the size and position of the underlying data representation.
If maxlen is not specified or is None , deques may grow to an arbitrary length. Otherwise, the deque is bounded to the specified maximum length. Once a bounded length deque is full, when new items are added, a corresponding number of items are discarded from the opposite end. Bounded length deques provide functionality similar to the tail filter in Unix. They are also useful for tracking transactions and other pools of data where only the most recent activity is of interest.
Deque objects support the following methods:
Add x to the right side of the deque.
Add x to the left side of the deque.
Remove all elements from the deque leaving it with length 0.
Create a shallow copy of the deque.
New in version 3.5.
Count the number of deque elements equal to x.
New in version 3.2.
Extend the right side of the deque by appending elements from the iterable argument.
Extend the left side of the deque by appending elements from iterable. Note, the series of left appends results in reversing the order of elements in the iterable argument.
Return the position of x in the deque (at or after index start and before index stop). Returns the first match or raises ValueError if not found.
New in version 3.5.
Insert x into the deque at position i.
If the insertion would cause a bounded deque to grow beyond maxlen, an IndexError is raised.
New in version 3.5.
Remove and return an element from the right side of the deque. If no elements are present, raises an IndexError .
Remove and return an element from the left side of the deque. If no elements are present, raises an IndexError .
Remove the first occurrence of value. If not found, raises a ValueError .
Reverse the elements of the deque in-place and then return None .
New in version 3.2.
Rotate the deque n steps to the right. If n is negative, rotate to the left.
When the deque is not empty, rotating one step to the right is equivalent to d.appendleft(d.pop()) , and rotating one step to the left is equivalent to d.append(d.popleft()) .
Deque objects also provide one read-only attribute:
Maximum size of a deque or None if unbounded.
New in version 3.1.
In addition to the above, deques support iteration, pickling, len(d) , reversed(d) , copy.copy(d) , copy.deepcopy(d) , membership testing with the in operator, and subscript references such as d[0] to access the first element. Indexed access is O(1) at both ends but slows to O(n) in the middle. For fast random access, use lists instead.
Starting in version 3.5, deques support __add__() , __mul__() , and __imul__() .
deque Recipes¶
This section shows various approaches to working with deques.
Bounded length deques provide functionality similar to the tail filter in Unix:
Another approach to using deques is to maintain a sequence of recently added elements by appending to the right and popping to the left:
A round-robin scheduler can be implemented with input iterators stored in a deque . Values are yielded from the active iterator in position zero. If that iterator is exhausted, it can be removed with popleft() ; otherwise, it can be cycled back to the end with the rotate() method:
The rotate() method provides a way to implement deque slicing and deletion. For example, a pure Python implementation of del d[n] relies on the rotate() method to position elements to be popped:
To implement deque slicing, use a similar approach applying rotate() to bring a target element to the left side of the deque. Remove old entries with popleft() , add new entries with extend() , and then reverse the rotation. With minor variations on that approach, it is easy to implement Forth style stack manipulations such as dup , drop , swap , over , pick , rot , and roll .
defaultdict objects¶
Return a new dictionary-like object. defaultdict is a subclass of the built-in dict class. It overrides one method and adds one writable instance variable. The remaining functionality is the same as for the dict class and is not documented here.
The first argument provides the initial value for the default_factory attribute; it defaults to None . All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.
defaultdict objects support the following method in addition to the standard dict operations:
If the default_factory attribute is None , this raises a KeyError exception with the key as argument.
If default_factory is not None , it is called without arguments to provide a default value for the given key, this value is inserted in the dictionary for the key, and returned.
If calling default_factory raises an exception this exception is propagated unchanged.
This method is called by the __getitem__() method of the dict class when the requested key is not found; whatever it returns or raises is then returned or raised by __getitem__() .
Note that __missing__() is not called for any operations besides __getitem__() . This means that get() will, like normal dictionaries, return None as a default rather than using default_factory .
defaultdict objects support the following instance variable:
This attribute is used by the __missing__() method; it is initialized from the first argument to the constructor, if present, or to None , if absent.
Changed in version 3.9: Added merge ( | ) and update ( |= ) operators, specified in PEP 584.
defaultdict Examples¶
Using list as the default_factory , it is easy to group a sequence of key-value pairs into a dictionary of lists:
When each key is encountered for the first time, it is not already in the mapping; so an entry is automatically created using the default_factory function which returns an empty list . The list.append() operation then attaches the value to the new list. When keys are encountered again, the look-up proceeds normally (returning the list for that key) and the list.append() operation adds another value to the list. This technique is simpler and faster than an equivalent technique using dict.setdefault() :
Setting the default_factory to int makes the defaultdict useful for counting (like a bag or multiset in other languages):
When a letter is first encountered, it is missing from the mapping, so the default_factory function calls int() to supply a default count of zero. The increment operation then builds up the count for each letter.
The function int() which always returns zero is just a special case of constant functions. A faster and more flexible way to create constant functions is to use a lambda function which can supply any constant value (not just zero):
Setting the default_factory to set makes the defaultdict useful for building a dictionary of sets:
namedtuple() Factory Function for Tuples with Named Fields¶
Named tuples assign meaning to each position in a tuple and allow for more readable, self-documenting code. They can be used wherever regular tuples are used, and they add the ability to access fields by name instead of position index.
collections. namedtuple ( typename , field_names , * , rename = False , defaults = None , module = None ) ¶
Returns a new tuple subclass named typename. The new subclass is used to create tuple-like objects that have fields accessible by attribute lookup as well as being indexable and iterable. Instances of the subclass also have a helpful docstring (with typename and field_names) and a helpful __repr__() method which lists the tuple contents in a name=value format.
The field_names are a sequence of strings such as [‘x’, ‘y’] . Alternatively, field_names can be a single string with each fieldname separated by whitespace and/or commas, for example ‘x y’ or ‘x, y’ .
Any valid Python identifier may be used for a fieldname except for names starting with an underscore. Valid identifiers consist of letters, digits, and underscores but do not start with a digit or underscore and cannot be a keyword such as class, for, return, global, pass, or raise.
If rename is true, invalid fieldnames are automatically replaced with positional names. For example, [‘abc’, ‘def’, ‘ghi’, ‘abc’] is converted to [‘abc’, ‘_1’, ‘ghi’, ‘_3’] , eliminating the keyword def and the duplicate fieldname abc .
defaults can be None or an iterable of default values. Since fields with a default value must come after any fields without a default, the defaults are applied to the rightmost parameters. For example, if the fieldnames are [‘x’, ‘y’, ‘z’] and the defaults are (1, 2) , then x will be a required argument, y will default to 1 , and z will default to 2 .
If module is defined, the __module__ attribute of the named tuple is set to that value.
Named tuple instances do not have per-instance dictionaries, so they are lightweight and require no more memory than regular tuples.
To support pickling, the named tuple class should be assigned to a variable that matches typename.
Changed in version 3.1: Added support for rename.
Changed in version 3.6: The verbose and rename parameters became keyword-only arguments .
Changed in version 3.6: Added the module parameter.
Changed in version 3.7: Removed the verbose parameter and the _source attribute.
Changed in version 3.7: Added the defaults parameter and the _field_defaults attribute.
Named tuples are especially useful for assigning field names to result tuples returned by the csv or sqlite3 modules:
In addition to the methods inherited from tuples, named tuples support three additional methods and two attributes. To prevent conflicts with field names, the method and attribute names start with an underscore.
classmethod somenamedtuple. _make ( iterable ) ¶
Class method that makes a new instance from an existing sequence or iterable.
Return a new dict which maps field names to their corresponding values:
Changed in version 3.1: Returns an OrderedDict instead of a regular dict .
Changed in version 3.8: Returns a regular dict instead of an OrderedDict . As of Python 3.7, regular dicts are guaranteed to be ordered. If the extra features of OrderedDict are required, the suggested remediation is to cast the result to the desired type: OrderedDict(nt._asdict()) .
Return a new instance of the named tuple replacing specified fields with new values:
Tuple of strings listing the field names. Useful for introspection and for creating new named tuple types from existing named tuples.
Dictionary mapping field names to default values.
To retrieve a field whose name is stored in a string, use the getattr() function:
To convert a dictionary to a named tuple, use the double-star-operator (as described in Unpacking Argument Lists ):
Since a named tuple is a regular Python class, it is easy to add or change functionality with a subclass. Here is how to add a calculated field and a fixed-width print format:
The subclass shown above sets __slots__ to an empty tuple. This helps keep memory requirements low by preventing the creation of instance dictionaries.
Subclassing is not useful for adding new, stored fields. Instead, simply create a new named tuple type from the _fields attribute:
Docstrings can be customized by making direct assignments to the __doc__ fields:
Changed in version 3.5: Property docstrings became writeable.
See typing.NamedTuple for a way to add type hints for named tuples. It also provides an elegant notation using the class keyword:
See types.SimpleNamespace() for a mutable namespace based on an underlying dictionary instead of a tuple.
The dataclasses module provides a decorator and functions for automatically adding generated special methods to user-defined classes.
OrderedDict objects¶
Ordered dictionaries are just like regular dictionaries but have some extra capabilities relating to ordering operations. They have become less important now that the built-in dict class gained the ability to remember insertion order (this new behavior became guaranteed in Python 3.7).
Some differences from dict still remain:
The regular dict was designed to be very good at mapping operations. Tracking insertion order was secondary.
The OrderedDict was designed to be good at reordering operations. Space efficiency, iteration speed, and the performance of update operations were secondary.
The OrderedDict algorithm can handle frequent reordering operations better than dict . As shown in the recipes below, this makes it suitable for implementing various kinds of LRU caches.
The equality operation for OrderedDict checks for matching order.
A regular dict can emulate the order sensitive equality test with p == q and all(k1 == k2 for k1, k2 in zip(p, q)) .
The popitem() method of OrderedDict has a different signature. It accepts an optional argument to specify which item is popped.
A regular dict can emulate OrderedDict’s od.popitem(last=True) with d.popitem() which is guaranteed to pop the rightmost (last) item.
A regular dict can emulate OrderedDict’s od.popitem(last=False) with (k := next(iter(d)), d.pop(k)) which will return and remove the leftmost (first) item if it exists.
OrderedDict has a move_to_end() method to efficiently reposition an element to an endpoint.
A regular dict can emulate OrderedDict’s od.move_to_end(k, last=True) with d[k] = d.pop(k) which will move the key and its associated value to the rightmost (last) position.
A regular dict does not have an efficient equivalent for OrderedDict’s od.move_to_end(k, last=False) which moves the key and its associated value to the leftmost (first) position.
Until Python 3.8, dict lacked a __reversed__() method.
Return an instance of a dict subclass that has methods specialized for rearranging dictionary order.
New in version 3.1.
The popitem() method for ordered dictionaries returns and removes a (key, value) pair. The pairs are returned in LIFO order if last is true or FIFO order if false.
move_to_end ( key , last = True ) ¶
Move an existing key to either end of an ordered dictionary. The item is moved to the right end if last is true (the default) or to the beginning if last is false. Raises KeyError if the key does not exist:
New in version 3.2.
In addition to the usual mapping methods, ordered dictionaries also support reverse iteration using reversed() .
Equality tests between OrderedDict objects are order-sensitive and are implemented as list(od1.items())==list(od2.items()) . Equality tests between OrderedDict objects and other Mapping objects are order-insensitive like regular dictionaries. This allows OrderedDict objects to be substituted anywhere a regular dictionary is used.
Changed in version 3.5: The items, keys, and values views of OrderedDict now support reverse iteration using reversed() .
Changed in version 3.6: With the acceptance of PEP 468, order is retained for keyword arguments passed to the OrderedDict constructor and its update() method.
Changed in version 3.9: Added merge ( | ) and update ( |= ) operators, specified in PEP 584.
OrderedDict Examples and Recipes¶
It is straightforward to create an ordered dictionary variant that remembers the order the keys were last inserted. If a new entry overwrites an existing entry, the original insertion position is changed and moved to the end:
An OrderedDict would also be useful for implementing variants of functools.lru_cache() :
UserDict objects¶
The class, UserDict acts as a wrapper around dictionary objects. The need for this class has been partially supplanted by the ability to subclass directly from dict ; however, this class can be easier to work with because the underlying dictionary is accessible as an attribute.
class collections. UserDict ( [ initialdata ] ) ¶
Class that simulates a dictionary. The instance’s contents are kept in a regular dictionary, which is accessible via the data attribute of UserDict instances. If initialdata is provided, data is initialized with its contents; note that a reference to initialdata will not be kept, allowing it to be used for other purposes.
In addition to supporting the methods and operations of mappings, UserDict instances provide the following attribute:
A real dictionary used to store the contents of the UserDict class.
UserList objects¶
This class acts as a wrapper around list objects. It is a useful base class for your own list-like classes which can inherit from them and override existing methods or add new ones. In this way, one can add new behaviors to lists.
The need for this class has been partially supplanted by the ability to subclass directly from list ; however, this class can be easier to work with because the underlying list is accessible as an attribute.
class collections. UserList ( [ list ] ) ¶
Class that simulates a list. The instance’s contents are kept in a regular list, which is accessible via the data attribute of UserList instances. The instance’s contents are initially set to a copy of list, defaulting to the empty list [] . list can be any iterable, for example a real Python list or a UserList object.
In addition to supporting the methods and operations of mutable sequences, UserList instances provide the following attribute:
A real list object used to store the contents of the UserList class.
Subclassing requirements: Subclasses of UserList are expected to offer a constructor which can be called with either no arguments or one argument. List operations which return a new sequence attempt to create an instance of the actual implementation class. To do so, it assumes that the constructor can be called with a single parameter, which is a sequence object used as a data source.
If a derived class does not wish to comply with this requirement, all of the special methods supported by this class will need to be overridden; please consult the sources for information about the methods which need to be provided in that case.
UserString objects¶
The class, UserString acts as a wrapper around string objects. The need for this class has been partially supplanted by the ability to subclass directly from str ; however, this class can be easier to work with because the underlying string is accessible as an attribute.
class collections. UserString ( seq ) ¶
Class that simulates a string object. The instance’s content is kept in a regular string object, which is accessible via the data attribute of UserString instances. The instance’s contents are initially set to a copy of seq. The seq argument can be any object which can be converted into a string using the built-in str() function.
In addition to supporting the methods and operations of strings, UserString instances provide the following attribute:
A real str object used to store the contents of the UserString class.
Changed in version 3.5: New methods __getnewargs__ , __rmod__ , casefold , format_map , isprintable , and maketrans .
Python's Counter: The Pythonic Way to Count Objects
Counting several repeated objects at once is a common problem in programming. Python offers a bunch of tools and techniques you can use to approach this problem. However, Python’s Counter from collections provides a clean, efficient, and Pythonic solution.
This dictionary subclass provides efficient counting capabilities out of the box. Understanding Counter and how to use it efficiently is a convenient skill to have as a Python developer.
In this tutorial, you’ll learn how to:
- Count several repeated objects at once
- Create counters with Python’s Counter
- Retrieve the most common objects in a counter
- Update object counts
- Use Counter to facilitate further computations
You’ll also learn about the basics of using Counter as a multiset, which is an additional feature of this class in Python.
Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.
Counting Objects in Python
Sometimes you need to count the objects in a given data source to know how often they occur. In other words, you need to determine their frequency. For example, you might want to know how often a specific item appears in a list or sequence of values. When your list is short, counting the items can be straightforward and quick. However, when you have a long list, counting things can be more challenging.
To count objects, you typically use a counter, which is an integer variable with an initial value of zero. Then you increment the counter to reflect the number of times a given object appears in the input data source.
When you’re counting the occurrences of a single object, you can use a single counter. However, when you need to count several different objects, you have to create as many counters as unique objects you have.
To count several different objects at once, you can use a Python dictionary. The dictionary keys will store the objects you want to count. The dictionary values will hold the number of repetitions of a given object, or the object’s count.
For example, to count the objects in a sequence using a dictionary, you can loop over the sequence, check if the current object isn’t in the dictionary to initialize the counter (key-value pair), and then increment its count accordingly.
Here’s an example that counts the letters in the word “Mississippi”:
The for loop iterates over the letters in word . In each iteration, the conditional statement checks if the letter at hand isn’t already a key in the dictionary you’re using as counter . If so, it creates a new key with the letter and initializes its count to zero. The final step is to increment the count by one. When you access counter , you see that the letters work as keys and the values as counts.
Note: When you’re counting several repeated objects with Python dictionaries, keep in mind that they must be hashable because they’ll work as dictionary keys. Being hashable means that your objects must have a hash value that never changes during their lifetime. In Python, immutable objects are also hashable.
Another way to count objects with a dictionary is to use dict.get() with 0 as a default value:
When you call .get() this way, you get the current count of a given letter , or 0 (the default) if the letter is missing. Then you increment the count by 1 and store it under the corresponding letter in the dictionary.
You can also use defaultdict from collections to count objects within a loop:
This solution is more concise and readable. You first initialize the counter using a defaultdict with int() as a default factory function. This way, when you access a key that doesn’t exist in the underlying defaultdict , the dictionary automatically creates the key and initializes it with the value that the factory function returns.
In this example, since you’re using int() as a factory function, the initial value is 0 , which results from calling int() without arguments.
Like with many other frequent tasks in programming, Python provides a better way to approach the counting problem. In collections , you’ll find a class specially designed to count several different objects in one go. This class is conveniently called Counter .
Getting Started With Python’s Counter
Counter is a subclass of dict that’s specially designed for counting hashable objects in Python. It’s a dictionary that stores objects as keys and counts as values. To count with Counter , you typically provide a sequence or iterable of hashable objects as an argument to the class’s constructor.
Counter internally iterates through the input sequence, counts the number of times a given object occurs, and stores objects as keys and the counts as values. In the next section, you’ll learn about different ways to construct counters.
Constructing Counters
There are a few ways for you to create Counter instances. However, if your goal is to count several objects at once, then you need to use a sequence or iterable to initialize the counter. For example, here’s how you can rewrite the Mississippi example using Counter :
Counter iterates over «mississippi» and produces a dictionary with the letters as keys and their frequency as values. In the first example, you use a string as an argument to Counter . You can also use lists, tuples, or any iterables with repeated objects, as you see in the second example.
Note: In Counter , a highly optimized C function provides the counting functionality. If this function isn’t available for some reason, then the class uses an equivalent but less efficient Python function.
There are other ways to create Counter instances. However, they don’t strictly imply counting. For example, you can use a dictionary containing keys and counts like this:
The counter now has an initial group of key-count pairs. This way to create a Counter instance is useful when you need to provide initial counts of an existing group of objects.
You can also produce similar results by using keyword arguments when you call the class’s constructor:
Again, you can use this approach to create a Counter object with a specific initial state for its keys and counts pairs.
In practice, if you’re using Counter to count things from scratch, then you don’t need to initialize the counts since they have a zero value by default. Another possibility might be to initialize the counts to 1 . In that case, you can do something like this:
Python sets store unique objects, so the call to set() in this example throws out the repeated letters. After this, you end up with one instance of each letter in the original iterable.
Counter inherits the interface of regular dictionaries. However, it doesn’t provide a working implementation of .fromkeys() to prevent ambiguities, such as Counter.fromkeys(«mississippi», 2) . In this specific example, each letter would have a default count of 2 despite of its current number of occurrences in the input iterable.
There are no restrictions on the objects you can store in the keys and values of a counter. The keys can store hashable objects, whereas the values can store any objects. However, to work as counters, the values should be integer numbers representing counts.
Here’s an example of a Counter instance that holds negative and zero counts:
In this example, you may ask, “Why do I have -15 tomatoes?” Well, that could be an internal convention to signal that you have a client’s order for 15 tomatoes, and you don’t have any in your current inventory. Who knows? Counter allows you to do this, and you can probably find a few use cases for the feature.
Updating Object Counts
Once you have a Counter instance in place, you can use .update() to update it with new objects and counts. Rather than replacing values like its dict counterpart, the .update() implementation provided by Counter adds existing counts together. It also creates new key-count pairs when necessary.
You can use .update() with both iterables and mappings of counts as arguments. If you use an iterable, the method counts its items and updates the counter accordingly:
Now you have 6 instances of i , 6 instances of s , and so on. You also have some new key-count pairs, such as ‘o’: 1 , ‘u’: 1 , and ‘r’: 1 . Note that the iterable needs to be a sequence of items rather than a sequence of (key, count) pairs.
Note: As you already know, there are no restrictions on the values (counts) that you can store in a counter.
Using objects other than integer numbers for the counts breaks common counter features:
In this example, the letter counts are strings instead of integer values. This breaks .update() , resulting in a TypeError .
The second way to use .update() is to provide another counter or a mapping of counts as an argument. In that case, you can do something like this:
In the first example, you update an existing counter, sales , using another counter, monday_sales . Note how .update() adds the count from both counters.
Note: You can also use .update() with keyword arguments. So, for example, doing something like sales.update(apple=10, orange=8, banana=3) works the same as sales.update(monday_sales) in the example above.
Next, you use a regular dictionary containing items and counts. In this case, .update() adds the counts of existing keys and creates the missing key-count pairs.
Accessing the Counter’s Content
As you already know, Counter has almost the same interface as dict . You can perform nearly the same actions with counters as you can with standard dictionaries. For example, you can access their values using dictionary-like key access ( [key] ). You can also iterate over the keys, values, and items using the usual techniques and methods:
In these examples, you access and iterate over the keys (letters) and values (counts) of your counter using the familiar dictionary interface, which includes methods such as .keys() , .values() , and .items() .
Note: If you want to dive deeper into how to iterate through a dictionary, then check out How to Iterate Through a Dictionary in Python.
A final point to note about Counter is that if you try to access a missing key, then you get zero instead of a KeyError :
Since the letter «a» doesn’t appear in the string «mississippi» , the counter returns 0 when you try to access the count for that letter.
Finding Most Common Objects
If you need to list a group of objects according to their frequency, or the number of times they appear, then you can use .most_common() . This method returns a list of (object, count) sorted by the objects’ current count. Objects with equal counts come in the order they first appear.
If you supply an integer number n as an argument to .most_common() , then you get the n most common objects. If you omit n or set it to None , then .most_common() returns all the objects in the counter:
In these examples, you use .most_common() to retrieve the most frequent objects in sales . With no argument or with None , the method returns all the objects. If the argument to .most_common() is greater than the current counter’s length, then you get all the objects again.
You can also get the least-common objects by slicing the result of .most_common() :
The first slicing, [::-1] , returns all the objects in sales in reverse order according to their respective counts. The slicing [:-3:-1] extracts the last two objects from the result of .most_common() . You can tweak the number of least-common objects you get by changing the second offset value in the slicing operator. For example, to get the three least-frequent objects, you can change -3 to -4 , and so on.
Note: Check out Reverse Python Lists: Beyond .reverse() and reversed() for hands-on examples of using the slicing syntax.
If you want .most_common() to work correctly, then make sure that the values in your counters are sortable. This is something to keep in mind because, as mentioned, you can store any data types in a counter.
Putting Counter Into Action
So far, you’ve learned the basics of creating and using Counter objects in your code. You now know how to count the number of times each object appears in a given sequence or iterable. You also know how to:
- Create counters with initial values
- Update existing counters
- Get the most frequent objects in a given counter
In the following sections, you’ll code some practical examples so you can get a better idea of how useful Python’s Counter can be.
Counting Letters in a Text File
Say you have a file that contains some text. You need to count the number of times each letter appears in the text. For example, say you have a file called pyzen.txt with the following content:
Yes, this is The Zen of Python, a list of guiding principles that define the core philosophy behind Python’s design. To count the number of times each letter appears in this text, you can take advantage of Counter and write a function like this:
Here’s how this code works:
- Line 5 defines count_letters() . This function takes a string-based file path as an argument.
- Line 6 creates an empty counter for counting the letters in the target text.
- Line 7opens the input file for reading and creates an iterator over the file content.
- Line 8 starts a loop that iterates through the file content line by line.
- Lines 9 to 11 define a list comprehension to exclude nonletter characters from the current line using .isalpha() . The comprehension lowercases the letters before filtering them to prevent having separate lowercase and uppercase counts.
- Line 12 calls .update() on the letters counter to update the counts of each letter.
To use count_letters() , you can do something like this:
Great! Your code counts the frequency of every letter in a given text file. Linguists often use letter frequency for language identification. In English, for example, studies on the average letter frequency have revealed that the five most common letters are “e,” “t,” “a,” “o,” and “i.” Wow! That almost matches your results!
Plotting Categorical Data With ASCII Bar Charts
Statistics is another field in which you can use Counter . For example, when you’re working with categorical data, you might want to create bar charts to visualize the number of observations per category. Bar charts are especially handy for plotting this type of data.
Now say you want to create a function that allows you to create ASCII bar chart on your terminal. To do that, you can use the following code:
In this example, print_ascii_bar_chart() takes some categorical data , counts the number of times each unique category appears in the data ( frequency ), and generates an ASCII bar chart that reflects that frequency.
Here’s how you can use this function:
The first call to print_ascii_bar_chart() plots the frequency of each letter in the input string. The second call plots sales per fruit. In this case, you use a counter as input. Also, note that you can use symbol to change the character for the bars.
Note: In the example above, print_ascii_bar_chart() doesn’t normalize the frequency values when it draws the charts. If you use data with high frequency values, then your screen will look like a mess of symbols.
When you’re creating bar charts, using horizontal bars allows you to have enough room for the category labels. Another helpful feature of bar charts is the possibility of sorting the data according to their frequency. In this example, you sort the data using .most_common() .
Plotting Categorical Data With Matplotlib
It’s nice to know how to create ASCII bar charts from scratch using Python. However, in the Python ecosystem, you can find several tools for plotting data. One of those tools is Matplotlib.
Matplotlib is a third-party library for creating statical, animated, and interactive visualizations in Python. You can install the library from PyPI using pip as usual:
This command installs Matplotlib in your Python environment. Once you’ve installed the library, you can use it to create your bar charts and more. Here’s how you can create a minimal bar chart with Matplotlib:
Here, you first do the required imports. Then you create a counter with some initial data about fruit sales and use .most_common() to sort the data.
You use zip() to unzip the content of sales into two variables:
- x holds a list of fruits.
- y holds the corresponding units sold per fruit.
Then you create a bar chart using plt.bar() . When you run plt.show() , you get a window like the following on your screen:
In this chart, the horizontal axis shows the name of each unique fruit. Meanwhile, the vertical axis indicates the number of units sold per fruit.
Finding the Mode of a Sample
In statistics, the mode is the most frequent value (or values) in a sample of data. For example, if you have the sample [2, 1, 2, 2, 3, 5, 3] , then the mode is 2 because it appears most frequently.
In some cases, the mode isn’t a unique value. Consider the sample [2, 1, 2, 2, 3, 5, 3, 3] . Here you have two modes, 2 and 3 , because both appear the same number of times.
You’ll often use the mode to describe categorical data. For example, the mode is useful when you need to know which category is the most common in your data.
To find the mode with Python, you need to count the number of occurrences of each value in your sample. Then you have to find the most frequent value (or values). In other words, the value with the highest number of occurrences. That sounds like something you can do using Counter and .most_common() .
Note: Python’s statistics module in the standard library provides functions for calculating several statistics, including the mode of unimodal and multimodal samples. The example below is just intended to show how useful Counter can be.
Here’s a function that computes the mode of a sample:
Inside mode() , you first count the number of times each observation appears in the input data . Then you use .most_common(1) to get the frequency of the most common observation. Since .most_common() returns a list of tuples in the form (point, count) , you need to retrieve the tuple at index 0 , which is the most common in the list. Then you unpack the tuple into two variables:
- _ holds the most common object. Using an underscore to name a variable suggests that you don’t need to use that variable in your code, but you need it as a placeholder.
- top_count holds the frequency of the most common object in data .
The list comprehension compares the count of each object with the count of the most common one, top_count . This allows you to identify multiple modes in a given sample.
To use this function, you can do something like this:
Your mode() works! It finds the mode of numerical and categorical data. It also works with single-mode and multimode samples. Most of the time, your data will come in a sequence of values. However, the final example shows that you can also use a counter to provide the input data.
Counting Files by Type
Another interesting example involving Counter is to count the files in a given directory, grouping them by file extension or file type. To do that, you can take advantage of pathlib :
In this example, you first create an iterator over the entries in a given directory using Path.iterdir() . Then you use a list comprehension to build a list containing the extensions ( .suffix ) of all the files in the target directory. Finally, you count the number of files using the file extension as the grouping criteria.
If you run this code on your computer, then you’ll get a different output depending on the content of your Pictures/ directory, if it exists at all. So, you’ll probably need to use another input directory for this code to work.
Using Counter Instances as Multisets
In math, a multiset represents a variation of a set that allows multiple instances of its elements. The number of instances of a given element is known as its multiplicity. So, you can have a multiset like <1, 1, 2, 3, 3, 3, 4, 4>, but the set version will be limited to <1, 2, 3, 4>.
Just like in math, regular Python sets allow unique elements only:
When you create a set like this, Python removes all the repeated instances of each number. As a result, you get a set with unique elements only.
Python supports the concept of multisets with Counter . The keys in a Counter instance are unique, so they’re equivalent to a set. The counts hold the multiplicity, or the number of instances, of each element:
Here, you first create a multiset using Counter . The keys are equivalent to the set you saw in the example above. The values hold the multiplicity of each element in the set.
Counter implements a bunch of multiset features that you can use to solve several problems. A common use case for a multiset in programming is a shopping cart because it can contain more than one instance of each product, depending on the client’s needs:
In this example, you create a shopping cart using a Counter object as a multiset. The counter provides information about a client’s order, which includes several learning resources. The for loop iterates through the counter and computes the subtotal for each product and prints it to your screen.
To reinforce your knowledge of using Counter objects as multisets, you can expand the box below and complete the exercise. When you’re finished, expand the solution box to compare your results.
Exercise: Calculate the Total Amount to Pay Show/Hide
As an exercise, you can modify the example above to calculate the total amount to pay at checkout.
Solution: Calculate the Total Amount to Pay Show/Hide
Here’s a possible solution:
In the first highlighted line, you add a new variable to hold the total cost of all the products you ordered. In the second highlighted line, you use an augmented assignment to accumulate every subtotal in total .
Now that you have an idea of what a multiset is and how Python implements them, you can take a look at some of the multiset features that Counter provides.
Restoring Elements From a Counter
The first multiset feature of Counter that you’re going to learn about is .elements() . This method returns an iterator over the elements in a multiset ( Counter instance), repeating each of them as many times as its count says:
The net effect of calling .elements() on a counter is to restore the original data you used to create the counter itself. The method returns the elements—letters in this example—in the same order they first appear in the underlying counter. Since Python 3.7, Counter remembers the insertion order of its keys as a feature inherited from dict .
Note: As you already know, you can create counters with zeroed and negative counts. If an element’s count is less than one, then .elements() ignores it.
The docstring of .elements() in the source code file provides an interesting example of using this method to compute a number from its prime factors. Since a given prime factor may occur more than once, you might end up with a multiset. For example, you can express the number 1836 as the product of its prime factors like this:
1836 = 2 × 2 × 3 × 3 × 3 × 17 = 2 2 × 3 3 × 17 1
You can write this expression as a multiset like <2, 2, 3, 3, 3, 17>. Using a Python’s Counter , you’ll have Counter(<2: 2, 3: 3, 17: 1>) . Once you have this counter in place, you can compute the original number using its prime factors:
The loop iterates over the elements in prime_factors and multiplies them to compute the original number, 1836 . If you’re using Python 3.8 or beyond, then you can use prod() from math to get a similar result. This function calculates the product of all elements in the input iterable:
In this example, the call to .elements() restores the prime factors. Then math.prod() computes 1836 from them in one go, which saves you from writing a loop and from having a few intermediate variables.
Using .elements() provides a way to restore the original input data. Its only drawback is that, in most cases, the order of items in the input won’t match the order in the output:
In this example, the resulting string doesn’t spell the original word, mississippi . However, it has the same content in terms of letters.
Subtracting the Elements’ Multiplicity
Sometimes you need to subtract the multiplicity (count) of the elements in a multiset or counter. In that case, you can use .subtract() . As its name implies, this method subtracts the counts supplied in an iterable or mapping from the counts in the target counter.
Say you have a multiset with your current fruit inventory and you need to keep it up to date. Then you can run some of the following operations:
Here, you use several ways to provide the input data to .subtract() . In all cases, you update the counts of each unique object by subtracting the counts provided in the input data. You can think of .subtract() as the counterpart of .update() .
Doing Arithmetic With Elements’ Multiplicity
With .subtract() and .update() , you can combine counters by subtracting and adding corresponding element counts. Alternatively, Python provides handy operators for addition ( + ) and subtraction ( — ) of element counts, as well as operators for intersection ( & ) and union ( | ). The intersection operator returns the minimum of corresponding counts, while the union operator returns the maximum of counts.
Here are a few examples of how all these operators work:
Here, you first add two counters together using the addition operator ( + ). The resulting counter contains the same keys (elements), while their respective values (multiplicities) hold the sum of counts from both involved counters.
The second example shows how the subtraction operator ( — ) works. Note that negative and zero counts result in not including the key-count pair in the resulting counter. So, you don’t see orange in the output because 8 — 9 = -1.
The intersection operator ( & ) extracts the objects with lower counts from both counters, whereas the union operator ( | ) returns the objects with higher counts from both involved counters.
Note: For further details on how Counter handles arithmetic operations, check out the class documentation.
Counter also supports some unary operations. For example, you can get the items with positive and negative counts using the plus ( + ) and minus ( — ) signs, respectively:
When you use the plus sign ( + ) as a unary operator on an existing counter, you get all the objects whose counts are greater than zero. On the other hand, if you use the minus sign ( — ), you get the objects with negative counts. Note that the result excludes objects whose counts are equal to zero in both cases.
Conclusion
When you need to count several repeated objects in Python, you can use Counter from collections . This class provides an efficient and Pythonic way to count things without the need for using traditional techniques involving loops and nested data structures. This can make your code cleaner and faster.
In this tutorial, you learned how to:
- Count several repeated objects using different Python tools
- Create quick and efficient counters with Python’s Counter
- Retrieve the most common objects in a particular counter
- Update and manipulate object counts
- Use Counter to facilitate further computations
You also learned the basics of using Counter instances as multisets. With all this knowledge, you’ll be able to quickly count objects in your code and also to perform math operations with multisets.
Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Counting With Python's Counter
Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

About Leodanis Pozo Ramos
Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.
Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:




Master Real-World Python Skills With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
Master Real-World Python Skills
With Unlimited Access to Real Python
Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:
What Do You Think?
What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.
Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal. Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!