hello everyone today we will do a quick objects and classes exercise where we will practice everything we've learned in previous tutorials and we will also talk about inheritance about private class members and i'll even share some tips on how you can avoid repetition so are you ready let's roll and we will begin by creating a new class which we will call guitar and just like any other class it will have an init method which takes in the self parameter now the init method is where we initialize some important information about our class so let's say we'd like to specify how many strings our guitar has to do this we will type self dot n underscore strings and we will assign it to 6. now what we have just created here is called an attribute which represents a piece of information that somehow relates to our guitar class we can then access these attributes from outside of our class definition in order to do this we will first need to generate a guitar object we will do this with guitar and an empty set of round brackets we can now assign this object to my underscore guitar and then right below we can simply print my guitar dot n underscore strings and hopefully we'll get six now let's save everything and let's give it a run and perfect we are now accessing one of our attributes but classes are not just about data they also deal with functionality so in addition to attributes we also have methods now in order to define a new method we will first use the def keyword followed by the name of the method which in my case will be play and in order to officially turn it into a method we will need to pass the self parameter into it if we do not pass this self parameter here if we just leave it like that we are actually creating a function not a method that's why the self parameter is very important and i'll show you the difference quickly inside a comment so whenever we call a function we simply specify the function name play but whenever we call a method we first call an object name followed by a dot and then the method name so dot play okay so we call the method on something while the function is quite long-standing that's the main difference let's go ahead and move on and what i'd like this method to do is i would like it to print some kind of a melody so in my case we will print [Music] which i'm sure everybody's familiar with we can now save this file and let's give it a run yeah nothing changed we're still printing six and the reason why nothing changed is because we haven't officially called the play method now we can do this in several ways so first of all we can call this method on the object itself so we will type my guitar dot play okay let's save this code and now it should work beautiful we can clearly see that this is the house of the rising sun playing here giving all these pom-pom pumps but there's another way let's get rid of this line of code and let's call our play method on the class itself so inside our init method we will add an additional line of self dot play okay let's save everything and let's see if it gives us the same result and there you go it's the exact same melody playing even though we haven't called it on the object we called it within the class now what happens here is that the init method is being automatically called every time we create a new object which is really really handy to know now this pretty much covers everything we've learned in the previous tutorial so if there's anything that you didn't understand please check out my objects and classes for beginners video and now let's go ahead and move on with inheritance so let's say we have a guitar store and we'd like to keep track of all the different guitar models we have in stock some of them are electric some of them are acoustic classic and so on now one solution is to copy this entire guitar class paste it below adjust guitar to electric guitar and then we can add a new attribute of self dot is distortion and we will set it to true but this seems highly inefficient just because of this tiny line of code we are repeating one two three four five six of them no no no no there must be a better solution so how about this what if we take our existing class and we use all of its attributes and methods to generate a new class so for example let's say our new class is called electric guitar once again but instead of copying the entire code content of our guitar class we will simply pass it into our new class now what we have done here is called inheritance we took all the data and all the functionality of what we call a parent class as in our guitar and we have passed it into a child class of electro guitar just like a family tree relationship a child is taking dna from their parents and you know so on so let's check if it worked we can then add the pass statement underneath our class definition and this is what you do when you don't want to make any changes to the class so if you'd like your parent class and your child class to be a hundred percent match you simply type the pass statement and you got it okay and then right below instead of assigning my guitar to guitar we will assign it to electric guitar and then just in case we will also check if we can access the end strings attribute of our parent class and yeah let's give it a run aha so not only we can access the n strings attribute of our parent class but we can also access its play method okay but what if we'd like to add some new methods to our child class let's say we'd like it to play our melody just a tiny bit louder and we can do this very easily as usual we will type def play louder to which we'll pass the self parameter and then we can go ahead and copy the print statement from our parent class and we'll slightly adjust it so at the end of the string we will add a dot upper method which will convert this entire pom pom pom sentence into uppercase letters awesome and then at the bottom of our code we will type my guitar dot play louder this time let's save it let's have a look boom there you go but that was easy but what if we'd like to replace some attributes so for example let's say that our electric guitar just happens to have eight strings now we don't really want to change it in the parent class because most guitars do not have eight strings so we want this change to only affect the child class and the way to do this is to first access the init method of the child class with def in it passing the self parameter into it but here's a problem since our child class inherited all of its attributes from the parent class we will also need access to the init method of the parent and this is where the super function comes in and i'm sure you've seen it a lot so we will type super with an empty set of round brackets followed by a dot in it with another set of empty round brackets we do not pass the self parameter here only in the above line of code so once we have access we can then replace our attribute as follows so self and strings we can reassign it to eight that's it now let's go ahead and double check that everything worked we will first print child class to which we will concatenate my guitar dot and strings and then below it we will print parent class and we'll concatenate guitar an empty set of round brackets followed by a dot and strings okay let's have a look boom amazing so our child class has eight strings while our parent class still remains with six of them now in addition to reassigning attributes in the child class we can also add new attributes and as you may guess we will do this with self then the attribute name color and we will set it to a set to a tuple of black and white one two three four five six perfect but what if we'd like to store some confidential information let's say we'd like to include the cost of this guitar as in how much this guitar cost to the store owner so let's say i'm charging my customers 500 bucks for this guitar while what i actually paid for it given by self dot cost is only 50 bucks and i don't want anybody to know this i would really appreciate it if this information is kept a secret now one solution which you may find online is converting this cost attribute into something called a private member makes a lot of sense right we can of course do this quite easily we will simply add two underscores in front of the attribute name so underscore underscore cost and then if we try to access this attribute in the exact same way we've been accessing the previous ones we'll print my guitar dot underscore underscore cost save everything let's give it a run we are getting a nasty error saying that there is no such attribute underscore underscore cost even though we can clearly see it's here okay so does it mean that our our cost is private i really wish it did i really wish i'm gonna show you how you can easily access it anyways okay so if we add an underscore followed by the name of the class which in our case is electric guitar and then we add underscore underscore cost our cost then is no longer private okay but what if we try to hide it somewhere okay let's copy this cost attribute and let's try to hide it in the parent function that might do the trick no that that might probably solve it so let's fix the indentation let's save everything and let's rerun our code and there you go it looks like it worked so we have this attribute error and it looks like everything is rainbows and butterflies no no because if we delete electric and we only leave guitar inside our print statement which is a perfect match to the parent class okay to this one now we rerun the code and we once again reveal the cost conclusion what we call private members in python has nothing to do with actual privacy which is being polite here it doesn't mean these members are private yeah it's relevant for other programming languages for example c plus plus but if we try to do this with python it's a recipe for disaster and even though the previous examples are quite a deal breaker we can also create some private methods and the way to do this is to type def underscore underscore secret which is the name of our private method well supposedly private method i should call it and we'll pass the self parameter into it and then right below i would like to print this guitar actually cost me a dollar symbol to which we will concatenate a private member from the parent class which has a special way of doing this so we are targeting the self dot underscore underscore cost attribute okay so we will type self dot underscore guitar which is the name of the class followed by underscore underscore cost which is the name of the private member that's it now let's go ahead and concatenate the rest of the sentence which is probably only an exclamation point yeah that's it and then instead of printing we will type my guitar dot underscore electric guitar underscore underscore secret and an empty set of round brackets let's save everything let's have a look beautiful we are revealing our secret once again now let's finish this exercise with a very handy tip let's say that now we are dealing with a bass guitar which in most cases has only four strings so we will then create a new class called bass guitar and we will inherit all the qualities of our guitar class and let's say that the only attribute we would like to change is the number of strings so do we really need to repeat these three lines of code time and again no so let's go back to our parent class and let's do the following so what if instead of hard coding 6 we will collect the number of strings as a parameter so in addition to our self parameter we will also collect and underscore strings and then instead of assigning self.n strings to 6 we will assign it to n strings now there's just a single problem with this entire syntax every time we create a new object we will need to specify the number of strings and in most cases it's going to be 6. so do we need to repeat it no we can simply set a default value to our n strings parameter so we'll add an equals 6 to the end of the parameter and that's it so if we specify a value that will be applied on self and strings but if we do not specify a value this will always be six and then we can simply add the pass statement to our base guitar class at the very bottom of the code we will print base guitar which takes in four and we will try to see if our n strings attribute returns four as well so let's save it let's have a look boom there you go it returns four so now let's try to adjust our electric guitar class as well so instead of having this uh self dot uh n strings equals eight line of code we will copy and strings equals 8 will get rid of self and we will pass it to our super init method that's it if we'd like to verify that everything worked we will do the following so we'll type my bass guitar has blah blah blah strings and my electric guitar has my guitar dot n underscore strings strings cool let's verify everything and there you go guys good job now you know how to handle all kinds of situations that relate to classes but if you need to practice a bit more i highly encourage you to check out my forests of object tutorial it will give you a very visual example of of how handy classes and objects are so definitely give it a try now thank you guys so much for watching i hope you enjoyed this tutorial and if you did please share it with the world if you have anything to say please leave me a comment if you'd like to be extra awesome you can always leave me a like you can subscribe to my channel and turn on the notification bell i'll see you guys very soon in a brand new tutorial so bye bye for now