The magic of the collections

Hi, everybody. Today I want to briefly summarize one of the great modules in Python: Collections

This module implements specialized container data types and provides an alternative to Python’s generic built-in containers, which can be found in the Lib/collections/init.py directory if you are interested in the source code

Based on my current learning experience, the following types are widely used:

The name of the Simple explanation
defaultdict Dict subclasses call factory functions to provide missing values
counter Dict subclasses used to evaluate hashable objects
deque A list-like container that can be manipulated from both ends
namedtuple Factory function for creating a tuple subclass with named fields
OrderedDict The dict that records the input order

If you are like me, don’t panic when you see the words factory function, hash object, container, etc., I was confused when I first saw them and skipped them, but later I found that you don’t need to understand them. If you are interested, you can look them up yourself

defaultdict

Basic concept

“Defaultdict” is a container defined in the module named “Collections”. It takes a function (the default factory) as its argument. Default is set to “int”, which is 0. Defaultdict if the key does not exist, and returns and displays the default value.

Let me explain in human terms: a dict that does not report errors when a key is not found

Examples of application

For a normal dict example, if we create a dictionary named person and the key is name, age, we will raise a KeyError if we try to call person[‘city’] because there is no city:

person = {'name':'xiaobai'.'age'18} :print ("The value of key 'name' is : ",person['name'])
print ("The value of key 'city' is : ",person['city'])

Out: The value of key  'name' is :  xiaobai
Traceback (most recent call last):
  File "C:\Users\E560\Desktop\test.py", line 17, in <module>
    print ("The value of key 'city' is : ",person['city'])
KeyError: 'city'

Copy the code

Now what if we try defaultDict again?

from collections import defaultdict
person = defaultdict(lambda : 'Key Not found') Key Not Found = 'key Not Found'

person['name'] = 'xiaobai'
person['age'] = 18

print ("The value of key 'name' is : ",person['name'])
print ("The value of key 'adress' is : ",person['city'[) Out: The value of The key'name' is :  xiaobai
     The value of key  'adress' is :  Key Not found
Copy the code

There is no problem this time. In fact, the fundamental reason is that when we create defaultdict, the first parameter we pass is the default value of all keys, and then we add name and age. When we finally query, if the key exists, we output the corresponding value. If it doesn’t, it prints the value ‘Key Not Found’ that we specified.

In addition, because defaultdict is passed as the default value for all keys when we create it, we can use this feature to implement other functions, such as:

from collections import defaultdict
d = defaultdict(list)
d['person'].append("xiaobai")
d['city'].append("paris")
d['person'].append("student")

for i in d.items():
    print(i)

Out: ('person'['xiaobai'.'student'])
     ('city'['paris'])

Copy the code

By default, all keys correspond to a list, so we can use the append method of list when assigning values. Or take this example:

from collections import defaultdict
food = (
    ('jack'.'milk'),
    ('Ann'.'fruits'),
    ('Arham'.'ham'),
    ('Ann'.'soda'),
    ('jack'.'dumplings'),
    ('Ahmed'.'fried chicken'),
)

favourite_food = defaultdict(list)

for n, f in food:
    favourite_food[n].append(f)

print(favourite_food) Out: defaultdict (< class'list'{>,'jack': ['milk'.'dumplings'].'Ann': ['fruits'.'soda'].'Arham': ['ham'].'Ahmed': ['fried chicken']})
Copy the code

Much the same as above, here you can expand your imagination and believe that defaultDict may be available at some point

counter

Basic concept

Counter is a subclass of dict. Thus, it is an unordered collection in which the elements and their respective counts are stored as dictionaries. This is equivalent to bag or multiset in other languages.

A counter that returns a dictionary, where key is the element that appears, and value is the number of occurrences of that element

Examples of application

The counter has nothing to say, what can also do, count bai!

from collections import Counter
# count list
count_list = Counter(['B'.'B'.'A'.'B'.'C'.'A'.'B'.'B'.'A'.'C'])  
print (count_list)

# count a tupleCount_tuple = Counter (,2,2,3,1,3,1,1,1 (2))print(count_tuple) Out: Counter ({'B': 5, 'A': 3.'C': 2})
     Counter({1: 4, 2: 3, 3: 2})
Copy the code

Counter is generally not used for dict and Set counts, because a dict key is unique and a Set itself cannot have repeating elements

Now we can count the food tuples directly from the defaultDict example:

from collections import Counter
food = (
    ('jack'.'milk'),
    ('Ann'.'fruits'),
    ('Arham'.'ham'),
    ('Ann'.'soda'),
    ('jack'.'dumplings'),
    ('Ahmed'.'fried chicken'),
)

favourite_food_count = Counter(n for n,f in food)  # count the number of occurrences of name
print(favourite_food_count)

Out: Counter({'jack': 2.'Ann': 2.'Arham': 1, 'Ahmed': 1})

Copy the code

deque

Basic concept

We can use deques when we need to add and remove elements quickly at both ends of the container. My personal understanding is that a deque is a container that can operate on both ends, similar to a list but faster than a list

Examples of application

There are many methods of deque, many of which are similar to lists and also support slicing

from collections import deque
d = deque()
d.append(1)
d.append(2)
d.append(3)

print(len(d))
print(d[0])
print(d[-1])

Out: 3
     1
     3
Copy the code

The great feature of deque is that we can operate from both ends:

d = deque([i for i in range(5)])
print(len(d))
# Output: 5

d.popleft()   Delete and return the leftmost element
# Output: 0

d.pop()       Delete and return the rightmost element
# Output: 4

print(d)
# Output: deque([1, 2, 3])

d.append(100)  Add elements from the right end

d.appendleft(-100) Add elements from the far left

print(d)
# Output: deque([-100, 1, 2, 3, 100])

Copy the code

For example, we can specify the maximum length of a deque when we define it. Like list, deques also support the extend method to facilitate list concatenation, but deques provide bidirectional operation:

From collections import deque d = deque([1,2,3,4,5], maxlen=9)# Set the total length unchanged
d.extendleft([0])  Add a list from the leftD.e xtend ([June])# extend a list from the right end
print(d) Out: a deque ([0, 1, 2, 3, 4, 5, 6, 7, 8], maxlen = 9)Copy the code

Now d already has 9 elements, and maxlen=9, if we add elements from the left, the rightmost element is automatically removed, and vice versa:

d.append(100)
print(d)
d.appendleft(-100)
print(d)

Out: deque([1, 2, 3, 4, 5, 6, 7, 8, 100], maxlen=9)
     deque([-100, 1, 2, 3, 4, 5, 6, 7, 8], maxlen=9)
Copy the code

Deque can also be used in many other ways, so please find your own treasure according to your own needs.

namedtuple

Basic concept

Name tuple. You might think of it as a tuple, and yes, I think of it as a tuple enhanced version of a namedtuple that turns a tuple into a convenient container. With namedtuple, we don’t have to use integer indexes to access the members of a tuple.

I think you can think of namedtuple as an immutable dictionary

Examples of application

First, let’s review how ordinary tuples access members:

person = ('xiaobai'18),print(the person [0]) Out: xiaobaiCopy the code

Now let’s look at the power of namedtuple:

from collections import namedtuple

Person = namedtuple('Person'.'name age city')        This is similar to defining a class
xiaobai = Person(name="xiaobai", age=18, city="paris") # similar to creating a new object
print(xiaobai) Out: the Person (name ='xiaobai', age=18, city='paris')

Copy the code

We create a namedTuple very much like we define a class, where Person is the name of the class, and the second argument is the name of the value of the namedTuple. It feels like an attribute in the class, but we don’t need a comma to separate it.

print(xiaobai.name)
print(xiaobai.age)
print(Xiaobai. city) out: 18 ParisCopy the code

“Cool, cool dead,” Guo Degang can not help but admire here

This approach to class call properties is nice and useful in some real-world scenarios. One last thing to remember is that we can’t change the value of a namedtuple:

xiaobai.name = 'laobai'Out: Traceback (most recent call last): File"C:\Users\E560\Desktop\test.py", line 5, in <module>
    xiaobai.name = 'laobai'
AttributeError: can't set attribute

Copy the code

OrderedDict

Basic concept

“OrderedDict” is itself a dict, but it is special in that it records the order in which the keys and values are inserted into the dict

Examples of application

from collections import OrderedDict
d = {}
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
print(d)

Out:{'a': 1, 'c': 3.'b': 2.'d'4} :Copy the code

As you can see, this is a normal dict because it’s out of order. Even if we add a, B,c, and D and assign value, the output order is not controllable. OrderedDict was created to solve this problem:

from collections import OrderedDict
d = OrderedDict()
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
print(d) Out: OrderedDict ([('a', 1), ('b', 2), ('c'And 3), ('d', 4))Copy the code

This output is much better because the insertion order is automatically recorded, and similarly, if we delete a key, the order of OrderedDict does not change:

from collections import OrderedDict

print("Before deleting:\n")
od = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3
od['d'] = 4

for key, value in od.items():
    print(key, value)

print("\nAfter deleting:\n")
od.pop('c')
for key, value in od.items():
    print(key, value)

print("\nAfter re-inserting:\n")
od['c'] = 3
for key, value in od.items():
    print(key, value) Out:'a'(1),'b'And (2)'c'And (3)'d', 4)
    
    After deleting:
    
    ('a'(1),'b'And (2)'d', 4)
    
    After re-inserting:
    
    ('a'(1),'b'And (2)'d'(4),'c', 3)
Copy the code

conclusion

Today I gave you a brief introduction to some of the basic container types for Collections, including:

Container type The characteristics of
defaultdict A dict that does not report errors for a Key cannot be found
counter Counter where key is the occurrence of the element and value is the number of occurrences of the element
deque A list that can operate in both directions
namedtuple Use to create a tuple with named fields
OrderedDict Dict that records the order in which keys are entered

I don’t think it’s too much of an overstatement to call them treasure, because these containers are very useful in real use scenarios, and I find that many tutorials don’t cover them, so I sincerely hope that they can help you. If THERE are any mistakes or omissions in my introduction, PLEASE comment on them and let’s make progress together!