Chapter 7. Classes - Lesson 9. Custom Containers

This video is like watching the formula 1, fastforward, for me and also confusing …
class TagCloud:
def init(self):
self.tags = {}
def add(self, tag):
self.tags[tag] = self.tags.get(tag, 0) + 1 - this is very confusing . I’ve always had problems when I had to increment something, don’t really know when / where in the code I have to write the incrementation. Really bumpy road :expressionless:

Also why tags wasn’t include here : def__init__(self, tags): - is it because it has no value ? Aaand this: tags,tag, tags, tag …my head is spinning like the wheel of fortune

Isn’t this : - self.tags[tag] - alomst the same as - self.tags.get(tag) ?

Starting from the top:

    def __init__(self):
        self.tags = {}

__init__ is the constructor of the TagCloud class. This means that every time I create a new instance of TagCloud, this bit of code is run before anything else is done so that the instance is built correctly with all the proper attributes initialised.

If I declare an attribute in __init__ without passing it in at the time I instantiate it like here (in other words I make a call like tag_cloud = TagCloud() when I create the instance) it only means that I do not pass an initial value so the class must make sure it is assigned something. Here we assign a {} to self.tags. This means self.tags becomes an empty dictionary. If I declared my __init__ like this: def __init__(self, tags), it means that I must supply a value when I instantiate it (create a new instance) like this: tag_cloud = TagCloud(some_initial_value_for_tags). NB: When you pass a initial value like this the initialisation only happens once! At the time you create the instance.

The next bit of code:

    def add(self, tag):
        self.tags[tag] = self.tags.get(tag, 0) + 1

uses this self.tags dictionary that you created in the __init__. You would make the following call from your instance eg tags_cloud.add(some_tag_value). Unlike when you include this in the constructor like I showed above, you can do this every time you call tags_cloud.add(some_tag_value) because you can call an instance’s methods as many times as you want but you can only create that instance once.

The following line of code does a lot of things and could be a bit confusing if you are new to python’s dictionary (dict) types.

self.tags[tag] = self.tags.get(tag, 0) + 1

Starting with self.tags.get(tag, 0). self.tags is the dictionary object we declared in the constructor (__init__). A dictionary is a collection where every entry in that collection has a unique key that can appear only once in the entire collection. Every key has a value and these key value “pairs” make up all the entries in the dict collection.

So, I can access the value in a number of ways, the first is self.tags[tag] if you know that tag is already a key in the dictionary (tag can be anything like “travis” or 0 or 23ab1f41 etc). If you do not know if it is in the dictionary, you can use the special method, get . In python, dictionaries has this special method, get (a dictionary is a class just like the classes you build here so it also has methods) which sends back the associated value if that key already exists in the dictionary. You can supply a default value just incase it does not exist. This is what the 0 in self.tags.get(tag, 0) does. So what happens here is that python will go look for a key that has the same value that your tag variable has. If it finds it, it will return that value, if it does not find it, it will return 0.

So what the line of code does, is it takes your tag , see if it is already a key in your dictionary self.tags. If it is, it will return the corresponding value and add 1 to it. If it does not exist, it will return 0 and then add 1 to it.

This is just a clever way to count the number of times you added (through tags_cloud.add ) that specific tag to your dictionary.

First of all thank you very much for explaining again to me. The first part I understand now, but the second ‘‘could be a bit confusing’’ is an understatement until I learn more about Python. That line of code it’s just overwhelming right now, having a moment : “is this really for me?”

''If it does not exist, it will return 0 and then add 1 to it. ‘’ this I don’t understand …? If it doesn’t exist, why it will be added 1 ?

Yes, that is a good question. What you need to understand here is this. When I have a dictionary object and I want to add a new key value pair, let’s say that pair is (1, 3) where 1 is the key and 3 is the value, then I do it like this, eg:

self.tags[1] = 3

So two things can happen. The first possible state is that a key with a value of 1 already exists in my dictionary. If this is the case then the statement above will replace the value currently assigned to this key with 3 and this now becomes its new value. The other state is where a record with key = 1 has not yet been added. So what this statement will then do is first create this new key in the dictionary and then assign the value 3 to it.

So this is what is happening on the left side of the equal sign below:

self.tags[tag] = self.tags.get(tag, 0) + 1

If a key with the value that tag does not exist in the dictionary yet, it will create one and assign the value of what ever self.tags.get(tag, 0) + 1 ends up being. If it does exist, then it will just change the value associated with tag to whatever self.tags.get(tag, 0) + 1 ends up being.

What happens here is quite clever. Python is going to first evaluate what is on the right hand side of the equation. So it is going to look into the dictionary and see if a key with the value that tag has, exists. If it finds nothing it is going to become 0+1 = 1. Then Python is going to the left hand side of the equal sign. This is like a new operation for Python. It has a value now (1) and with this value it checks again if tag already exists in the dictionary. If it does not then it will create this new entry with a key = tag in the dictionary and assign the 1 that it got on the right hand side of the equation as the value to this entry.

I have to read it 2 or 3 times to fully understand, but it makes sense and thank you again! and thank for your patience with me, I really appreciate it!

but unfortunately for me, I don’t have the logical thinking, yet anyway, to come up with a line of code like this: self.tags[tag] = self.tags.get(tag, 0) + 1 - I’m starting to think maybe programming isn’t for me, maybe

We all start with not knowing. Dont be despondent. You only come up with these clever lines of code after doing many other less clever lines!

1 Like

I’m literally stuck…can’t get through…Making Custom Containers, Private Members and Properties are literally a pain in my … back :)) I’ve watched the videos again and again, but still can’t understand them and I won’t go further until I do …I’ve started to search other resources but still nothing …brain freeze