Object Oriented Programming with Python – Full Course for Beginners

Object Oriented Programming with Python – Full Course for Beginners
Spread the love

it’s important for software developers  to understand object-oriented  programming  in this course jim from gym-shaped  coding will teach you all about  object-oriented programming in python  object-oriented programming it could be  what is holding you back from being a  great python developer and as well as  landing your first job as a software  engineer  welcome everyone to python  object-oriented programming course now  if you struggle to understand the  concepts of object-oriented programming  in the past then you are totally fine  and you are in good hands because in  this course i’m going to make sure that  this will be the last tutorial that you  will ever watch about classes and the  complex concepts that comes with object  oriented programming and we are going to  do this by developing a real python  application that is going to be very  cool to write and we will add to its  complexity step by step and throughout  the way we will understand everything  that we need to know about  object-oriented programming now there  are going to be some requirements to  this course i do expect from everybody  to know at least about functions  variables if statements and as well as  for loops and if you know those things  from other programming languages then  this is also fine so with that being  said let’s get started now to explain  why you should write object oriented  programs i will explain the concepts  based on a store management system that  we will start developing together so  starting to think about how to take our  first steps with such a program we could  first think about tracking after the  items that we have right now in our  store so one way we could get started we  could create those four variables to  start tracking after our items so as you  can see we have our first variable item  one equals to phone and then we have  three more variables that are  intentionally starting with the prefix  of item one so that we could describe  that those four variables are related to  each other by following the correct  naming conventions now you might think  that those four variables are related to  each other only because it uses the same  prefix of item one for python those are  just four variables with different data  types so if we were to print the type  for each of those four variables now we  would receive their types with no  surprises right we will receive string  and integer for price quantity and price  total now i want to focus on those  specific outputs right now because as  you can see for each of the types we  also see the keyword of class now this  means that those data types are actually  instances of strings or integers so in  python programming language each data  type is an object that has been  instantiated earlier by some class and  for the item1 variable that has been  instantiated from a string type of class  and for the price quantity and price  total those have been instantiated from  a class that is named int meaning  integer so it could have been nicer if  we could tell python that we want to  create a data type of our own it will  allow us to write a code that we can  reuse in the future easily if needed now  each instance could have attributes to  describe related information about it  and we can think about at least some  good candidates for attributes we could  have for our item data type like its  name  price or quantity all right so let’s go  ahead and start creating our first class  so i will clean everything from here and  we’ll go ahead with it so it is going to  be divided into two parts the first one  will be the creation of the class and  the second one will be the part that i  will instantiate some objects of this  class now when i say creating an  instance or creating an object basically  i mean to the same thing so you might  hear me saying one of those all right so  let’s go ahead and say class and then  this needs to be followed by the name of  the class that you want to create so we  would like to give it the name of item  and then inside of this class in the  future we are going to write some code  that will be very beneficial and very  useful for us so we won’t repeat  ourselves every time that we like to  take similar actions but for now  temporarily i’m going to say here pass  so we will not receive any errors inside  this class definition all right so now  that we have created our class then we  are allowed to create some instances of  this class so let’s go ahead and say  item one is equal to item and that  action is equivalent to creating an  instance of a class just like if you  were to create a random string  then you will say something like the  following this is equivalent to this one  as well so it is very important to  understand how classes are working in  python so i will delete this line  because this was just for an example and  now i said that we are allowed to assign  some attributes to instances of a class  so let’s go ahead and start creating  attributes and that will be achievable  by using the dot sign right after the  instance of a class and here you can say  that you want to give it an attribute  like a name that will be equal to phone  and item1.price could be equal to  100 and item one dot quantity could be  equal to  five for example now in that stage you  might ask yourself what is the  difference between the random variables  that we have created to those four lines  well here we actually have a  relationship between those four lines  because each one of the attributes are  assigned to one instance of the class  and i could preview this by going ahead  and try to print the types of item one  now and as well as the types of the  attributes of  name price and quantity now with name  price and quantity we are not going to  have any surprises because we assigned  string type attributes to the item  object but if we were to print that then  check out the result if i was to run  this program so you can see that now we  have a data type of item here and that  is the big difference between what we  have seen previously to this thing that  we have just created so now we  understand how we can create our own  data types now let’s go ahead and see  what are the rest of the benefits using  object oriented programming okay so  until now we understood how to assign  attributes to instances we should also  understand now how we can create some  methods and execute them on our  instances now if we will take as an  example the built-in class of string  then you know that we have some methods  that we can go ahead and execute for  each of our strings and for this example  you can see that i grab an instance of a  string that i named random str and then  i go ahead in the next line and execute  the upper method which if you remember  is responsible to grab all the letters  and turn them to uppercase now the  biggest question here is how we can go  ahead and design some methods that are  going to be allowed to execute on our  instances well the answer is inside our  class so we could go inside our class  and write some methods that will be  accessible from our instances so we  could go ahead and say def  and give our method a name now a good  candidate for a method that we’d like to  create now is actually calculate total  price because as we understand it could  have been nice if we were to have a  method that will go ahead and calculate  the result multiplying item1.price with  item1.quantity so we can get the total  price for that specific item now before  we go ahead and complete this function  then i’m going to just create one more  instance of this item by also deleting  those two lines because we understood  the example so i’m just going to change  those to item 2  like that and i’m going to use something  like  laptop and change the price to 1000 and  say that we have three of those now just  a quick side note when you will hear me  say methods then i basically mean to  functions that are inside classes  because in terms of python or in any  programming language when you have  isolated definitions with this keyword  then those are considered to be called  functions but when you go ahead and  create those functions inside classes  then those are called methods so that is  an important point that you should  understand because i’m going to call  those methods from now okay so now if i  was to continue by opening up and  closing those parentheses then you are  going to see one parameter that is  generated that python wants us to  receive intentionally now the reason  that this happens  python  passes the object itself as a first  argument when you go ahead and call  those methods now if i was to go here  and say item1 dot calculate total price  then the action that we are doing now is  calling this method but when you go  ahead and call a method from an instance  then python passes the object itself as  a first argument every time so that is  why we are not allowed to create methods  that will never receive parameters now  you will see this if i was to remove the  first parameter and say something like  pass now if i was to execute  this program now then you are going to  see type error calculate total price  takes 0 positional arguments but one was  given so in simple words what this  exception says is that python tries to  pass one argument and you are not  receiving any parameter so that is very  problematic and that is why you always  have to receive at least one parameter  when you go ahead and create your  methods now since we always receive this  parameter then it is just a common  approach to call this self it was okay  if i was to call it something like my  param or i don’t know something else but  you never want to mess up with common  conventions across different python  developers so that is why just make sure  that you leave it as self every time now  if i was to go ahead and  run this program then you’re gonna see  that we are not going to receive any  errors so this means that this method  has been implemented correctly now let’s  see how we are going to benefit from  creating this method because it should  go ahead and create a calculation for us  using price and quantity so i will  intentionally receive here two more  parameters which we could name just x  and y for now and we could just say  return x multiplied by y and now i will  go ahead and pass in here two additional  arguments and it will be item1.price  the second one will be quantity so that  is going to work because when you call  this method in the background python  passes this as an argument and then it  passes this second argument and then  this has been passed as a third argument  so that is perfect and if i was to run  that and actually print this so excuse  me for running this  before printing it so i will  surround this  expression with this print built-in  function and i will run that and you’re  gonna see 500 as expected now i could do  the exact same thing for calculating the  total price of our second item so if i  was to grab this and paste this in in  this line and actually change this to  item two and change this one to item two  and as well as this one then i will  receive  three thousand as expected and that is  how you can create a metal alright so  until that point we understood that we  can assign attributes and as well as  creating some methods that we can go  ahead and use them from our instances  directly like those two examples in that  line and as well as in that line now in  that episode we are going to solve some  more problems that we have in terms of  best practices in object-oriented  programming and things that you are  going to see in each project that is  based on oop all right so let’s get  started now one of the first problems  that we have here is the fact that we  don’t have a set of rules for the  attributes that you would like to pass  in in order to instantiate an instance  successfully and what that means it  means that for each item that i want to  go ahead and create i need to hard code  in the attribute name  like those in here and it could have  been nicer if we could somehow declare  in the class that in order to  instantiate an instance successfully  name price and quantity must be passed  otherwise the instance could not have  been created successfully so what that  means it means that it could have been a  great option if we could somehow execute  something in the background this second  that we instantiate an instance and  there is a way that you can reach such a  behavior and that is by creating a  special method with a very unique name  which is called double underscore init  double underscore now you might hear  this term as well as called as  constructor basically that is a method  with a unique name that you need to call  it the way it is intentionally in order  to use its special features now the way  that this is going to work is by  creating  it the following way so it will be  double underscore and as you can see i  already have auto completion for some  very special methods that are starting  and ending with double underscore now  the collection of those methods are used  to be called magic methods and we are  going to learn a lot of more magic  methods that you have in oop but the  first one that we are going to start  with will be the init double underscore  like that all right so now that we have  created this method then let’s actually  see what this method does in the  background so when you go ahead and  create an instance of a class then  python executes this double underscore  init function automatically so what that  means it means that now that we have  declared our class python is going to  run through this line and then since an  instance has been created and we have  double score init method designed then  it is going to call the actions that are  inside this double underscore init  double underscore method now in order to  prove you that then i’m going to start  with a very basic print here that will  say i am created  like that now we got here one instance  and here we got another one so we should  see i am created twice and in order to  avoid confusions then i’m going to  delete those print lines from here so we  can see a cleaner picture all right so  if we were to run our program then you  can see that we have im created twice  and that is because python called this  double underscore init double underscore  method twice thanks to those two  instances that we have created all right  so now that we use the double underscore  init function in this class we should  take benefit from it and solve some more  problems in order to implement oop best  practices now if you remember in the  beginning of this tutorial i said that  one of the problems that we have till  this point is the fact that we still  hard code in the attributes in that way  by saying dot name dot price dot  quantity and that is something that we  can for sure avoid now let’s see how we  can start avoiding creating those  attributes hard-coded for each of the  instances here so we can actually  benefit from the double underscore init  method that we have designed and let’s  see how now we understand that for each  instance that we will create it will go  ahead and call this double underscore  init method automatically so what that  means it means that not only we can  allow ourselves to receive the sales  parameter because this is a mandatory  thing that we should do because python  in the background passes the instance  itself as a first argument we could in  addition take some more parameters and  then do something with them so as a  starter let’s say that we would like to  receive one more parameter that we could  name it name and as you can see  automatically python is going to  complain how the name argument is not  filled in here so  now i could go ahead and pass in the  argument of phone for that one and for  the second one i can go ahead and pass  in the argument of laptop now once i  have created this then i can actually go  ahead and change my print line a little  bit so it will be a unique print line  where i can identify from where each  print line came from so i can go ahead  and say an instance  created  and use a column here and then refer to  the name like that and now that we have  created this then if we were to run our  program then you’re gonna see unique  sentences and instances created for the  phone and as well as for the laptop all  right so now that we have done this then  there is something that is still not  quite perfect because we still pass in  the attribute of name here and here so  now pay attention how the init method  has to receive the self as a perimeter  as well and we already know the reason  for that and the fact that we have self  as a parameter here could actually allow  us to assign the attributes from the  init method so that we will not have to  go ahead and assign the attribute of  name for each of the instances we create  so what that means it means that i can  dynamically assign an attribute to an  instance from this magic method which is  called double underscore init so if i  was to say self  dot name so i’m assigning the attribute  of name to each instance that is going  to be created or created yet and i’m  making that to be equal to the name  that is passed in from here so what that  means it means that now i can allow  myself to delete  this line and then  this line so as you can see now i have a  dynamic attribute assignment thanks to  this self.name equals name that we have  wrote here and to test that the  attribute assignment worked then i can  go down here and use two more lines that  will look like the following so i will  print item  item1.name and i will also print item2  dot name and in order to avoid  confusions then i’m going to get rid of  this line so we could only see the print  lines from here and now if i was to run  that then you can see that we receive  phone and laptop so it means that we  were able to assign the attributes  dynamically and that is perfect and now  that we get the idea of that then we  should also do the same for the rest of  the attributes that we’d like to receive  so we also got the price and quantity to  take care of so i’m going to go to my  init method and i’m going to receive  again  price  and quantity and i’m going to do the  exact same thing so i’m going to assign  the attribute of price and that will be  equal to  price and the quantity will be equal to  the quantity and you can also see that  again python complains about the price  and the quantity not being passed in  here so i can say 100 and then 5  and then i can delete those  and then i can do the same here i could  pass in 1000 and then 3 and delete those  and in order to prove you that this is  going to work then i’m going to copy  myself a couple of times and change this  to quantity i mean  price  this one will be price as well  this one will be quantity and this one  as well and now if i was to run that  then you can see that the results are as  expected so that is a way that you  should work with the double underscore  init method you should always take care  of the attributes that you want to  assign to an object inside the double  underscore init method meaning inside  the constructor now a couple of side  notes that are quite important to  remember when we work with classes now  when we go ahead and use the double  score init method this doesn’t mean that  we cannot differentiate between  mandatory parameters to non-mandatory  parameters so say that you currently  don’t know how much you have from a  specific item then you can go ahead and  by default receive this quantity  parameter as zero because it is  realistic situation that you currently  don’t know how much phones you have on  your store so you can directly go ahead  and use a default value for that for  example  zero and then this will mean that you  will not have to pass in those five and  three here and now in order to show you  the results of that if i was to run our  program then you can see that we  received zero twice for those two prints  in here so that is something that you  want to remember and one more quite  important point that i’d like to talk  about now is the fact that you can  assign attributes to specific instances  individually so say that you want to  know if the laptop has numpad or not  because some laptops are not having the  numpad on the right side of the keyboard  but this is not a realistic attribute  that you would want to assign to a phone  and that is why you can go ahead and let  me delete those print lines by the way  and that is why you can go ahead and say  something like item two dot has  numpad equals to false like that and  that is something that you want to  remember because the fact that you use  some attribute assignments in the  constructor doesn’t mean that you cannot  add some more attributes that you would  like after you instantiate the instances  that you would like to alright so now  that we understood this then there is  still one small problem that is left  that we need to solve now pay attention  how the calculate total price still  receives the x and y as parameters and  the question that we ask now is  why it still receives those parameters  well we could for sure now not receive  those parameters because as we know for  each method that we design in classes  then the object itself is passed in  argument and i know that i repeated this  couple of times but this is where i fail  to understand classes so that is why it  is very important to understand this  behavior and we already know that the  object itself passed as an argument so  that’s why we receive self and so this  means that now we could just return  self.price multiplied by self.quantity  and this will mean that we don’t really  have to receive those parameters because  we assign those attributes  once the instances has been created so  this means that we have access to those  attributes throughout the methods that  we are going to add here in this class  in the future so in order to test that  this works then i’m going to  delete this example for now and i’m  going to say print item 1  dot  calculate total price so we will be able  to return the result here and i will do  the same for  item  two um sorry only this one now to show  some real number other than zero then i  will go ahead and pass in here  quantities so i will say one and  three for example because i don’t want  to multiply a large number with a zero  and that could come from here so i will  run that and you see that we receive the  expected results so now we completely  understand the big picture how to work  with the constructors in classes and  what are the best practices that you  should go ahead and implement all right  so now that we understood this then we  might think that we have done everything  perfectly but actually i want to show  you what will happen if we were to pass  in here a string besides  an integer and run our program so if we  were to run that then you can see that  we are screwing things up here because  this function for example thinks that it  should print the string  three times because you’ll see we have  1000 multiplied by three that is being  returned in here so it shows us one  thousand once  one thousand  twice and then one more time so what  that means it means that we have to  validate the data types of the values  that we are passing in so there are a  couple of ways to achieve this and one  way is by using typings in the  parameters that you’re declaring inside  here so a great starter will be for  example to declare that a name must be a  string now let me first take this back  and change those to integer and then go  here and design those parameters so in  order to specify a typing then you  should go ahead and create a column sign  followed by the type of the data type  that you expect to receive here so if i  was to pass in here only the object  reference to the class of str then it  will mean that it will have to accept  strings only and i can preview that by  changing this to an integer and you’re  gonna see that we have a complaint here  that says expected type str got int  instead and that is perfect so now that  we have done this then i’m going to do  the same for the price itself and price  we could actually  do the same thing with it  by passing in float now when we pass  float it is okay to also pass integers  and that is something very unique with  floats and integers together so that is  okay to use the typing of float and for  the quantity we don’t need to specify a  typing because the fact that we passed a  default value of integer already marked  this parameter as to be integer always  so that is why for example if i was to  leave this as it is and change the  quantity to a string then you’re gonna  see that it is going to complain because  the default value is already an integer  so it expects for an integer all right  so those things are actually great  setups to make our init function more  powerful but we might still want to  validate the received values in the  following way so say that you never want  to receive a negative number of quantity  and you never want to receive a negative  number of price so that is something  that you cannot achieve by the typings  in here but there’s actually a great way  to work this around and that will be by  using assert statements now a third is a  statement keyword that is used to check  if there is a match between what is  happening to your expectations so let’s  see how we can get work with assert so  i’m actually going to delete this from  here and i’m going to organize our init  method a little bit i’m going to say  here a comment and i will say assign to  self object  and i will say up top something like  run validations to the received  arguments  all right so now it is a great idea to  validate that the price and quantity are  both greater than or equal to zero  because we probably don’t want to handle  with those when they are negative  numbers and we want to crash the program  so we could say assert and pay attention  that i use it as a statement not a  built-in function or something like that  and i can say here  price is  greater than or equal to  zero now once i set this then i can also  do the same for  quantity actually so let me do that  quickly  by  this way and then once we have this then  i can actually  go ahead and run our program and you  will see that i will not receive any  arrows but the second that i change this  quantity to negative 1 for example and  this one being negative 3 then i will  have some errors that will say assertion  error now you can see that the fact that  we see here assertion error  is quite a general exception that  doesn’t mean anything now what is so  beautiful with assert you can add your  own exception messages right near of it  as a second argument so  let’s go up top here and go back to  those two lines so the first argument  that is passed to the statement is the  statement that would like to check but  if we were to say here comma and use a  string to say  actually a formatted string and i can  say  price  and then refer to the value of it  is not greater than  0 like that  i can add an explanation mark here and i  can use the same thing  copy that with a comma and paste this in  here and change this quantity  and then refer to the value of it  and say that it is not equal to i mean  greater than or equal to zero so it  needs to be actually changed to greater  than or equal to  like that  and same goes for  here  and i have some  space here that should be deleted all  right so now if i was to execute our  program then you can see that we receive  assertion error quantity  minus one is not greater or equal than  zero so i should delete this  then here for that and now it is perfect  so now we understand that using the  assert statement could allow us to  validate the arguments that we receive  and also it allows us to catch up the  bugs as soon as possible  before going forward with the rest of  the actions that we like to take within  this program so let me actually change  those back to valid values like that  and that is perfect alright so until  this point we learned about how to work  with the constructor and we also learned  about how to assign different attributes  to instances that are going to be unique  per instance which means that you can go  ahead and create as much as instances as  you want and you have the control to  pass whatever values you’d like to for  the name price and quantity now consider  a situation that you’ll want to make use  of an attribute that is going to be  global or across all the instances now a  good candidate for example of this could  be a situation that you’ll want to apply  a sale on your shop so this means that  you want to go ahead and having the  control of applying some discount for  each one of the items and that is a good  candidate for creating an attribute that  is going to be shared across all the  instances now we call those kind of  attributes class attributes and the kind  of attribute that we have learned till  this point is actually called in a full  name instance attributes so about  instance attributes we know everything  and we learned how to work with it but  we did not work it with the other kind  of the attributes which we will do in  this tutorial which is called again a  class attribute so a class attribute is  an attribute that is going to be belong  to the class itself but however you can  also access this attribute from the  instance level as well let’s go ahead  and see a good candidate for a class  attribute that you want to go ahead and  create it so that’s gonna be going to  our class here and just in the first  line inside our class i can go ahead and  create a class attribute so let’s go  ahead and create an attribute like pay  rate equals to 0.8 and the reason that  i’m doing this is because i said that  there is going to be 20 percent of  discount so i probably want to store an  attribute that will describe how much i  still need to pay  so i will say here the pay rate after  20 percent discount like that okay so  now that we have created this then let’s  see what are the ways that we can access  this attribute now if i was to go down  and actually deleting one of those and  say something inside this print line  that will look like the following so i  will try to access to the reference of  the class itself so i’m not going to  create an instance like that besides i’m  just going to bring in the reference to  the class level itself and i’m going to  try to access this attribute by saying  pay underscore rate now if i was to run  that then you’re going to see that as  expected we see this class attribute  because that is a way that you can  access those class attributes now this  might be confusing but i said a minute  ago that you can also access those class  attributes from the instance level well  let’s see if that is true so if i was to  duplicate those lines twice by using the  shortcut of control d  then let’s go ahead and change those to  item one  and this one to item two now see how i  try to access the pay rate attribute  from the instance although we don’t have  such an instance attribute now if i was  to run that then you’re gonna see that  we still have the access to see that  class attribute well that might be  confusing and that might be hard to  understand why that is happening well  there is actually something that we need  to understand when we work with  instances in python so when we have an  instance on our hand then at first this  instance tries to bring the attribute  from the  instance level at first stage but if it  doesn’t find it there then it is going  to try to bring that attribute from the  class level so what that means it means  that item one did some thinking here and  say to itself okay so i don’t have this  attribute right in here because that is  just not an attribute that assigned to  me so i’m going to try to search that  from the instance level and then i’m  going to find it and print it back so  that is exactly what is happening here  item 1 and item 2 are instances that  could not find the pay rate attribute on  the instance level so both of them went  ahead and tried to bring this attribute  from the class level and since it really  exists in the class level then we were  able to access those now to even give  you a better idea of what is going on  here then i’m going to do one more  additional thing now i will delete this  first print line and i will go ahead and  delete those attributes from here as  well now there is a built-in magic  attribute not a magic method that you  can go ahead and see all the attributes  that are belonging to that specific  object and that is achievable by using  this double underscore dict double  underscore like that so this will go  ahead and try to bring you all the  attributes that are belonging to the  object that you apply this attribute and  want to see its content so i will go  ahead and  copy this one and paste this in for the  instance level as well so this should  give me all the attributes for class  level  and the second line  should do this for the  instance level all right and if i was to  run that then let’s explore the results  for a second now you can see that at the  first line we see this pay rate  attribute but in the second line we  never see it we see name price and  quantity and you can also pay attention  that this magic attribute is actually  responsible to take all the attributes  and convert this to a dictionary and  that is from where the  keyword coming from it is just a  shortened version of a dictionary so  that is a very useful magic attribute  that you can go ahead and use if you  just want to see temporarily for  debugging reasons all the attributes  that are belonging to some object all  right so now that we understood this  then let’s take it to a real life  example and come up with a method that  will go ahead and apply a discount on  our items price so that will be by  creating a method that will be belong to  each of our instances and that means  that we can go ahead and come up with a  method that we could name apply discount  so let’s go ahead and start working on  this so i’m going to say def apply  discount and pay attention that i’m  using a new method inside a class here  so  right inside of this then at first we  need to figure out how we are going to  override an attribute that is belonging  to an instance and we already know that  we can do that with the self keyword so  it will be self  dot price  and that will be equal to self.price  meaning the older value of this  attribute  multiplied by the pay rate now you might  expect that we could access this  directly like that but if you remember  that is actually belonging to the item  class itself now this might be confusing  because this method already inside this  class so you might think already that  you can access it directly by saying pay  rate because it is already inside the  class but that is actually not going to  work because you can either access it  from the class level or the instance  level as we understood previously so i  can go ahead and say item dot pay rate  like that and there you have a method  that can go ahead and basically override  the price attribute for one of your  items now to show you that this works  then i can only use one instance for now  and i can go ahead and call this method  by say apply discount and i can also  now try to print the attribute of price  for this item  one and we should see 80 right so if we  were to run that then we’re going to see  that we are going to receive 80.0 as  expected now we should not forget the  option that you might also want to have  a different discount amount for a  specific item so say that one day you’ll  have 20 items and only for the laptop  you want to have a 30 discount but it is  going to be a bad idea changing the  class attribute to 0.7 because it will  affect all the items that you have right  now on your hand so what you can do  instead is you can assign this attribute  directly to one of the instances that  you would like to have a different  discount amount for so let’s go ahead  and see an example for this so i will  allow myself to bring back the item of  laptop and then what i can do to apply a  30 discount for this item is assigning  the exact same attribute to the instance  so i can go ahead and use a item tool  dot pay on the score rate  is equal to  0.7 now what will happen here is that  for item 2 it will find the attribute of  pay rate in the instance level so item 2  does not really have to go ahead to the  class level and bring back the value of  pay rate because at first look it is  going to find it in the instance level  but for item 1 it is different it is  still going to read from the item level  which is going to be 0.8  so now if we were to try to use item two  dot apply discount and as well as  printing the price now then let’s see  what will happen so i will uncomment  this line to not see this print for now  and i will go ahead and execute our  program now you can see that we still  however receive 800  and what this means this means that the  discount that has been applied is still  20  and where this is coming from well this  is coming from this method here that no  matter what we try to pull the pay rate  from the class level so a best practice  here will be to change this to self and  that way if we overwrite the pay rate  for the instance level then it is going  to read from the instance level but for  item one if we try to access the pay  rate from the instance level then this  is still great because we did not assign  a specific pay rate for item one so it  is going to pull that from the class  level now if we were to try to run that  then you’re gonna see now that we have  expected results and if we were to also  uncomment the first print line for the  item one and rerun our program then you  can see that for item one we had twenty  percent discount and for item two we had  thirty percent discount so when it comes  to accessing class attributes you might  want to reconsider how you want to  access them when you come up with some  methods and specifically for creating a  method like apply discount it is a great  idea to access it from the instance  level so you also allow the option of  using a pay rate that is assigned to the  instance level okay so now that we  understood completely about the  differences between a class two and  instance attribute let’s jump ahead to  the next topic now you see that i have  deleted those print lines that i have  down below and i came up with five  instances that i have created here so  you might also want to create those five  instances immediately so that is why i  will recommend you to go ahead to my  repository accessing this class  attributes directory and then code  snippets and then  go ahead and copy the code from these  five underscore items.py file okay so  considering a situation that your shop  is going to be larger in the future  meaning that you are going to have more  items then the more items that you are  going to have the more filtration like  things that you want to do in the future  but what is problematic currently with  our class is the fact that we don’t have  any resource where we can just access  all the items that we have in our shop  right now now it could have been nicer  if we could somehow  have a list with all the item instances  that have been created until this point  but currently there is not an approach  that will give us a list with five  elements where each element will  represent an instance of a class so in  order to come up with such a design then  here is a wonderful candidate for  creating a class attribute that we could  name all and once we do this then we’re  gonna see how we are going to add our  instances to that list so i will go  ahead and start by going here and use an  old attribute so it will be  all  equals to an empty list now we need to  figure out how we are going to add our  instances for each time that we are  going to go ahead and create an instance  now if you remember the double  underscore init method is being called  immediately once the instance has been  created so it might be a wonderful idea  going down below inside this double  underscore init method and use a code  that will be responsible to append to  that list every time that we create an  instance and that will be as easy as  saying something like the following so  first you could pay attention that i  actually wrote some commands in this  double underscore init function like run  validations and assign to self object so  it might be a great idea to start with a  comment here that will say actions  to execute just to really have a great  separation between the different things  that we are doing so now inside here i  can say item  dot all and you can see that i use the  class object first and then that is a  list so i can use  dot append and then i will just append  the self object now we know that self is  actually the instance itself every time  that it is being created so once we go  ahead and launch such a command inside  the init function then for each instance  that is going to be created this whole  list is going to be filled with our  instances now to show you that i can  jump a line after we create the  instances and we can say print  item dot all and now if i was to run our  program then you are going to see that  we are going to have a list with five  instances if i was to scroll right a bit  then you can see that i have exactly  five elements and that is perfect now  that’s going to be extremely useful if  you want to do something with only one  of the attributes of your instances so  say that you would like to print all the  names for all of your instances then you  can use easily a for loop to achieve  such a task so we can go ahead and say  for  instance  in  item dot all and you can say print  instance dot name and once we come up  with this then you can see that we have  all the names for all the instances that  we have created so that is going to be  useful here and there especially if you  know how to use the filter function for  example to apply some special things on  some of the instances that are matching  your criteria all right so now that we  understood this then let’s also take  care of one problem that we saw  previously now if i was to use a ctrl z  a couple of times  and still use this print item.all  now you could see that the way that the  object is being represented is not too  friendly now it could have been nicer if  we could somehow change the way that the  object is being represented in this list  here now there’s actually a way to  achieve this by using a magic method  inside our class now there is a magic  method that is called  double underscore repr and repr stands  for representing your objects so that is  why you can actually go ahead and use  this magic method and then you will have  the control to display your objects when  you are printing them in the console now  i actually recommend watching a video  that compares between a method that is  similar to it which is called double  underscore str and you can take a look  in the description of this entire series  to actually watch the video that i’m  talking about all right so let’s go  ahead and use the repair method to  understand how this is going to work so  i’m going to say def inside our class  and i’m going to use double underscore  re pr double underscore and as expected  it will receive the self now what we can  do now is returning a string that will  be responsible to represent this object  now obviously we don’t want to use  something that is not unique for each of  the instances because say that i was to  use now return item something like that  and  run our program then you can see that  i’m going to receive a list with this  string five times but it is going to be  hard to identify  which  instance represents each string here so  it could be helpful if we were to return  a string that could be unique so i’m  going to close the console here and go  ahead here and use a formatted string  and in order to make this unique it is a  best practice to represent it exactly  like we create the instance  like that so what i’m going to do here  is leaving the item and use a  brackets opener and the closure and then  i’m going to make the return string here  as much as equal as possible to the way  that we create  those instances so i will start by  typing here single quotes to escape from  the double quotes that are coming from  here and i’m going to refer to the value  of name by using self.name and then i  will leave my single quotes and i will  use a  comma like that and then i will go ahead  and refer to the value of our price i  will use one more comma and i will say  self.quantity  now if we were to execute our program  again then you can see that now we  receive a list that is way more friendly  than what we have seen previously and  you can also see that this  first element for example is quite  equivalent to this line here now you  might be curious why i worked so hard to  return the representative version of our  objects the same way that we create them  so that is just a best practice  according to python’s documentations  because it will help us to create  instances immediately by only the effort  of copying and pasting this to a python  console so if you think about it right  now if you open a python console and you  import this class then it will be as  easy as grabbing this  and pasting to the python console and  then you will have an instance being  created so that is the single reason  that i have came up with this approach  and also for sure i just wanted to  return a unique string that will really  represent our instance and you can see  that it is very easy to identify the  instances of our class with this list  and with this approach all right so  until this point we understood how we  can change the way that we represent our  objects and we also understood how we  can access to all of our instances by  this class attribute that we  intentionally named all now in this part  we are going to take a look to solve one  more problem that we have in terms of  best practices when we are going to  extend this application and add more  features now you can see that until this  point we maintain our data as code in  this main.py file by only instantiating  those five items now when we will look  to extend this application and add some  more features then we might have a  harder life to add those features  because the actual data and the code are  maintained in the same location meaning  in the same main.py file now you could  have think about creating a database  that will maintain this information but  i want to keep things more simple for  the purposes of this tutorial and that  is why i’m going to use something that  is called csv that you might have heard  of  csv stands for comma separated values so  this means that you could go ahead and  use a csv file and you could store your  values as comma separated where each  line will represent a single structured  data and csv is a great option here  because it allows the data to be saved  in a table structured format all right  so let’s go ahead and create a csv file  and i will actually go ahead and name  this  items.csv like that and i will go ahead  and paste in some  csv content that will be responsible at  the end of the day represent the same  data that we look to have here so you  can see that at the first line i have  name price and quantity and you can see  that those are comma separated so those  represents the columns that we are going  to have as the data that we are going to  maintain and in the second line and  further we are going to have some data  that will represent the actual data that  we look to maintain so if we were to now  split the panes then we can see that  those are quite equivalent and now we  should only look for a way to read this  csv file and actually instantiate those  objects now you can see that i have a  suggestion by pycharm to install a  plugin that will support csv files so  i’m going to just click on that and  install those plugins and you can see  that i will have a csv reader here and  we will see if we will be able to see  this data in a table which will be a lot  nicer so let’s go ahead and install this  and now you can see that i have some  more options that i can actually go  ahead and use from here i know that this  is quite small but actually you have  some tabs that you can go ahead and  click on them and if i was to click on  table editor and actually  give this  file more focus then you can see that i  actually have the best way to read this  data now you can see that i have my  columns you can see that i have my rows  and that is quite nice now i can really  go ahead and visualize my data more  nicer and it is just more common way to  maintain your data okay so now that we  understood how csv files are working  let’s go ahead and read our csv files  and instantiate the instances in a  generic way so it makes sense to delete  those five lines and i’m going to use  those lines  below the apply discount and use a  method that i could name instantiate  from csv  like that now you can see that this one  is also going to receive self because if  you remember i said that in each method  that we will design we need to receive  at least one parameter that will be  passed as the instance itself because  this is how python oop works now the  problem is we are not going to have any  instances on our hand to call this  method from the instance because this  method is actually designed for  instantiating the object itself so this  means that this method could not be  called from an instance so the way that  this is going to be solved is by  converting this method into a class  method now a class method is a method  that could be accessed in the following  way so i will use this line to delete  that and it could be accessed from the  class level  only so this will look like item  dot instantiate from csv and then in  here we will probably pass our csv file  so this method should take full  responsibility to instantiate those  objects for us so now that we understood  this let’s go ahead and see how we can  create a class method so for sure we  need to delete the self and i know that  we have errors but we are going to solve  each one of those just in a second now  in order to convert this to a class  method we need to use a decorator that  will be responsible to convert this  method into a class method now  decorators in python is just a quick way  to change the behavior of the functions  that we will write by basically calling  them just before the line that we create  our function so we could use the add  sign and use the class method  in here and then this instant sheet from  csv method will be a class method all  right so now that we understood this  then we should also understand one more  piece of information before we go ahead  and design this method now i want to  show you what will happen if i was to  delete the entire name and try to  recreate this function here and i will  just say instantiate  from csv again now pay attention what  will happen if i was to open up and  close the parentheses now you can see  that it still receives a parameter but  this time it is named cls  now what is going on here and the thing  that is going on here is the fact that  when we call our class methods then the  class  object itself is passed as a first  argument always in the background so it  is a bit like the instance where it is  also passed as the first argument but  this time when we call a class method in  this approach then the class reference  must be passed as a first argument so  that is why you should still receive at  least one parameter but we probably  understand that we could not name this  self because that is just going to be  too much confusing okay so now let’s go  ahead and write some code to read the  csv file and instantiate some objects  now i’m going to go up top first and i’m  going to import a library that is called  csv so i will go here and i will use an  import csv line because that will be the  library that will take full  responsibility to read the csv file and  then we will see how we can instantiate  some objects all right so now i can go  ahead and use a context manager to read  the items.csv file now both of those  files are located in the same location  so i can just directly say wait open  items dot csv  and the permission that i will be  passing here could be r because we only  look to read this and i will say as  f  like that now inside this open i will go  ahead and use some method to directly  read this csv which at the end of the  day will be responsible to convert this  into a python dictionary so i will say  reader is equal to csv  dot dict reader like that and i will  pass in the content of our file like  that now this method should go ahead and  read our content as a list of  dictionaries but at the end of the day  we should also go ahead and convert this  into a list so i will go ahead and  create one more variable that will be  equal to items and i will just convert  the reader into a list and that’s it and  now that we have completed the actions  that we wanted to complete by reading  this csv file let’s go ahead and use a  shift tab to indent out and now before  we go ahead and instantiate some objects  let’s go ahead and see the results of  iterating over the items list now i will  go ahead and use for item in  items  and then i will just use print items to  show you the behavior of that and excuse  me it should be item all right so now  that we understood this then let’s go  ahead and see what we have in those  lines so after our class definition we  only go ahead and call this  item.instantiate from csv method so if i  was to  run that then you can see that i receive  some dictionaries in separated lines and  that is because i iterate over a list of  dictionaries in here and that is just  perfect all right so the only thing that  we miss right now is creating instances  now besides printing those then we could  now say something like item and open up  and close parentheses  and this should be enough to instantiate  our instances now i can go ahead and  pass my arguments in here by basically  reading the keys from a dictionary so i  can say name  is equal to item dot get  and that will  receive name and now i can add a comma  and duplicate this line twice and change  those accordingly so this will be price  and this will be quantity and now i need  to replace my key names so it will be  price here and then quantity right there  and now let’s go ahead and see what will  happen if i was to call this method and  as well as calling the attribute of  item.all  because this one stores all the  instances inside the list now if i was  to go ahead and run it then you can see  that i have some errors now you’ll see  that the errors are related to the price  and you can see that we receive is not  greater than or equal to zero now let’s  go ahead and fix this very quickly so in  the items.csv you can see that those are  actually integers that are greater than  zero so the problem is probably the fact  that those are passed as strings so we  need to go ahead and pass those as  integers so i’m going to convert those  into  int  like that and  now let’s go ahead and see if we will  have any problems as i expect to have  any problem because the quantity should  complain about the same thing and you  can see that this is exactly what is  going on here so i can use the same for  quantity  like that and  work with that and you can see that now  we see our instances perfectly now i  want to show one more problem that we  could have in the future and we should  avoid now so those three lines are going  to work with this  structure of data but if i was to change  the price of our keyboard to something  like  74.90 something like that  and re-execute our  file then you can see that we will  receive some problems so we need to  convert the price not to an integer but  to a float like that and that is the  only way to get over this because we  don’t want to convert the price to an  integer directly because it could be  float so now we could go ahead and  execute and you can see that now it  works perfectly although we see the  prices as 100.0  but that is something that we will look  into it in the future but for now it  works perfect and now we are ready to  jump on to our next topic okay so now  that we completely understood the class  methods let’s go ahead and also  understand what static methods are now a  static method should do some work for  you that has some logical connection to  a class so for example if you want to  check if a number is an integer or a  float then this is a good candidate for  creating a static method because this  has some connection to the class that we  work with so it makes sense to check if  a price of an item has a decimal point  and by saying has a decimal point i  obviously count out those that are point  zero now to be honest static and class  methods could look very alike to you but  we will explain the main differences  very soon okay so i will use those lines  to create our first static method now  let’s go ahead and use the def keyword  and we will name this method is  underscore integer because we said that  we’d like to write a static method that  will check if a received number is an  integer or not now if i was to open up  and close parentheses this would  obviously receive itself now i want you  to take a closer look what will happen  if i was to change this method into  being a static method and the approach  is going to be pretty much the same like  we have done  with the class method we will use a  decorator that is called static method  and this should be responsible to the  conversion so i will go ahead and  use this line and i will say at static  method like that now pay attention  how the received perimeter turned into  the regular orange color that we are  familiar because that is just a regular  parameter that we receive now this means  that the static methods are never  sending in the background the instance  as a first argument and that is unlike  the class methods the class methods are  sending the class reference as a first  argument and that is why we had to  receive the cls and that is why it is  intentionally colored with purple but  with static methods we never send the  object as the first argument so that is  why we should relate to the static  method like a regular function that just  receives parameters like we are familiar  with isolated functions now i will go  deeper on this just in a few minutes but  let’s go ahead and finish up our static  method first so this should receive  num as one parameter because we should  receive at least something to check if  it is an integer or not all right so now  that we are inside this method  then i can go ahead and use a couple of  if statements to check if the received  argument is an integer or not now if you  remember we said that we’d like to  we will count  out the floats that are  decimal that are 0.0 okay  meaning  for example 5.0  10.0 and so on all right so now that we  understood this let’s go ahead and use  an if statement here so if and we will  call the built in function that is  called is instance  and this should receive two arguments  and we can understand what this function  is going to do for us it is going to  check if the  received parameter is an instance of a  float or an integer so we will pass in  as the first argument the num and as the  second argument the flow  without calling those parentheses so  only the reference to the float keyword  so this conditional should go ahead and  check if the num is a floating number or  not  now inside this if statement i will say  return  num  dot is  integer so by saying dot is integer then  i basically say  count out the floats that are decimal  that are point zero  so this means that if i was to pass in  here a number like 10.0 then this will  return false but remember that this will  enter here because it thinks it is a  float because it is represented in that  way and so the is underscore integer  should check if the point is zero and it  should return false accordingly now i  will also use an else if statement here  to basically check if it is integer by  itself so i will say el if is  instance num  and check if it is an instance of an  integer then i will just return true and  if it is just something else then i will  just say  return false like that so now that we  have designed this method then let’s  take a look how we can call it so now i  will just remove this and this i’m not  actually going to instantiate anything  i’m just going to show you how you can  access to the static method so i will  just call this item dot is integer and i  will just pass in a number that i would  like to check if it is an integer or not  now for sure we like to print this so we  will see the result now let’s go ahead  and pass in seven  so you can see that we receive true now  if i was to pass in 7.5 then i would  receive false and what is happening in  the background it is the fact that it  enters here but it sees that it is not  an integer so it returns false but if i  was to change this to 7.0  then this should sorry about that this  should still return  true because what is happening it is  entering inside this conditional and  then it checks if it is an integer but  we said that this method counts out the  floats that are 0.0 so it returns true  still so that is a perfect design all  right so i have came up with a new file  which i will just explain here when to  use a class method and when to use a  static method so we can completely  understand the differences between those  because i remember myself i had a very  tough time to understand why i need this  and why i need the other one so that  will be the main question that i will be  answering in this python file so don’t  feel like you have to copy and paste the  code following along what i am  explaining here by listening should be  enough all right so in this file i will  just go ahead and create this class item  that we have  right and i will use pass to not receive  errors now when we will use a static  method so we will use a static method  when we want to do something that should  not be unique per instance exactly like  we have done previously so each integer  is a method that is just going to be  responsible to check if a number is  integer or not so that is why i could  allow myself to include this under the  item just like i could use this def as  an isolated function right above the  class and that was also okay but i  prefer to not do that because although  this is a method that has nothing to do  with instance that is somehow related to  the item class so that is the reason you  want to create this as a static method  like we have designed previously and the  reason that you would like to create a  class method  is for instantiating instances from some  structured data that you own so exactly  like we have done we have created a  class method that was responsible to  read the csv file and creating some  instances so as i wrote here those are  used to manipulate different structures  of data to instantiate objects like we  have done with the csv file we could  also use a class method like install  sheet from a json file  or from a yaml file those just are  different ways to maintain data in the  best practice way and that is the code  that you look to include inside your  class methods that is why they should be  existing in any class especially if you  look to instantiate hundreds of objects  on your programs so it is a great idea  to have at least one class method like  we have done in the item class now the  only main difference between a class  method and to a static method is the  fact that static methods are not passing  the object reference as the first  argument in the background it is  noticeable from the fact that we don’t  have a special highlight purple in my  case for the first parameter so if you  remember if i was to go ahead and use  here a first parameter like num then you  will see that this is the first  parameter that is colored with orange  because that is a regular parameter but  that is purple because this is a  mandatory parameter that we should  receive because what i have just  explained so those are the main  differences between a static method to a  class method now if you remember i  intentionally said that the class  methods and the static methods could  only be called from the class level but  however those also could be called from  instances so as you can see i can  actually instantiate an object and call  the is integer and as well as the  instant sheet from something you can  just pass in here a number like five and  i will not receive any errors and if i  was to run the helper then you can see  that i don’t have any error now i’m  going to be honest with you i never saw  a reason to call a static method or a  class method from the instance level but  that is just an option that exists i  know that it is very very confusing but  that is something you are rarely going  to see and like i said i never saw a  great reason to call a static method or  to call a class method from an instance  so my recommendation to not confuse you  is just not going with calling those  from the instance level alright so i  minimized the code that we wrote so far  in the class item now in order to start  solving the problems that we will solve  in this episode then i’m going to create  here two instances so i will say phone  one  is equal to an item and let’s give it a  name like jsc phone v10  and then just  use a random price and quantity and i  will copy and paste this and use another  variable like phone 2 and i will  increase the version by 10 and let’s say  that this price for the phone 2 should  be 700 all right so now that we have  created two instances of a phone pay  attention that those two items are  phones so we could think about some  attributes that could represent phones  in real life think about an attribute  like broken phones because we could have  some phones that could have been broken  and so we cannot really mark it as a  phone that we could really sell so this  means that we could go ahead and say  phone one dot broken phones  let’s say that we have unfortunately one  broken phone on our hand right now so i  will go ahead and design the same  attribute for our second phone and now  that we have came up with this realistic  attribute then the next step that we  might think about could be creating a  method that will go ahead and calculate  the phones that are actually not broken  meaning subtracting the quantity by the  broken phones amount because this is  totally making sense and then we can  understand what are the phones that we  could go actually and sell them in the  future but we have a couple of problems  creating a method that will go ahead and  calculate such a thing because we cannot  really go ahead inside our item and do  this smooth enough because we don’t  really have the broken phones attribute  assigned to self and we cannot actually  go ahead and create this method inside  this item class because this method is  not going to be useful for other  hundreds of items that you will go ahead  and create this just represent a phone  kind of item so in order to solve this  problem in terms of best practices in  object oriented programming then we  could go ahead and create a separated  class that will inherit the  functionalities that the item class  brings with it and that is exactly where  we could benefit from inheritance and we  could go ahead and create a separated  class that we could name phone and then  this phone class will inherit all the  methods and all the attributes that item  class has so let’s go ahead and simulate  that so i’m not going to delete the  instances yet but i’m going to go ahead  here and create a class that i will name  it phone now pay attention that i will  not use a semicolon and i will use those  brackets and i will specify what class i  would like to inherit from so i will  inherit from item and then i will just  use a pass temporarily because i would  not like to use additional functionality  right now inside this class okay so now  that we have created this class then  let’s go ahead and first execute our  program where at the first stage the  instances will be item instances  and this should not have any problems  because we know that we can create those  item instances and we will not receive  any errors but if we were to change  those to  phone  like that then we should still not  receive any arrows and that’s just a  basic way that you could use inheritance  in order to represent different kinds of  objects when you want to do that now  this could also be applied to other  realistic programs that you want to come  up with them by your own but in my case  it totally makes sense to create some  classes where each class will represent  a kind of an item and then i could go  ahead and inherit from the item class  in each of the child classes that i will  go ahead and create in the future i  could also use another class for a kind  of item like laptop and then i could go  ahead and use a separated functionality  for that now when we talk about classes  that we inherit from then those are  considered to be called parent classes  and when we use multiple classes that  inherits from that parent class then  those are considered to be called child  classes so those are just terms that you  want to be familiar with when we talk  about object-oriented programming and  from here we will see more advanced  things that you can go ahead and do with  your child classes all right so now  let’s go ahead and understand some more  advanced things about inheritance now  throughout this series we learned that  it is not a great idea to assign  attributes manually once we create those  instances and the better way to do that  is actually going ahead and creating our  constructor and pass the value that we  like to immediately in the instance  creation exactly like here so in order  to solve this then we gonna need to  figure out how we are going to do that  because creating the constructor inside  this phone class is going to be a little  bit tricky because we don’t really want  to break the logic that the development  score in it brings with the parent class  but we’d also like to pass in an  additional attribute like broken phones  that we will go ahead and deal with that  attribute and assign it to the self  object exactly like we have done in the  second part of our series so in order to  keep the logic the same for this child  class and as well as receive some more  attributes then for now i’m going to go  ahead and copy the code in our  constructor and just paste this in  right inside our phone class and that’s  making sense temporarily because we  receive the exact same parameters that  we should receive when we instantiate an  instance and we also have now the  control to receive some more parameters  like we want to do with the broken  phones so let’s go ahead here and say  broken  so i will just scroll here and i will  say broken phones is equal to zero let’s  also receive a default value for that  and let’s go ahead and type in a  validation for the broken phones so i  will allow myself to just copy that and  paste this in and we’ll use a third  quantity i mean broken phones is greater  than or equal to zero and i will change  this to  broken phone  like that actually broken phones and  this should  be exactly like we have done with the  quantity and now let’s go ahead to the  section of assign to self object and we  can use self.broken  phones is equal to broken phones like  that  and you can see that here we have  actions to execute now it could have  been nicer if we could also create a  class attribute for the phone class and  that will mean that we could go ahead  here and say all is equal to an empty  list  and then we could go ahead and  use a phone dot all dot append like that  and now if i was to go ahead and run  this program then you can see that i  will not receive any arrows now to check  that this works then i’m also going to  pass in here one and i’m going to do the  same here as well and i’m going to  remove those all right i’m going to  remove the hard-coded attributes and the  program still works now i’d also like to  test this by applying one of the methods  that we have wrote so far and that will  be obviously a method that i’d like to  use from the parent class because we  inherit those methods so i can go ahead  and use  phoneone dot  calculate total price and it makes sense  to print this so i will go ahead and  print that and you can see that print  phone one dot calculate total price and  now if i was to run that then you can  see that i receive a result so this  means that i don’t have any errors now  i’m not sure if you paid attention to  this but if i was to scroll up a bit  then you’re gonna see that the  constructor in the chat class is  complaining about something and let’s  hover the mouse and see what is the  warning now you can see that it says to  us call to double underscore init of  super class is missed and what that  means it means that when we initialize  the double underscore init method inside  the child class then python expects for  some function to be called intentionally  now this function is named super and  what super allows us to do it allows us  to have full access to all the  attributes of the parent class and by  using the super function we don’t really  need to hard code in the attribute  assignment like we have done with the  name price and quantity and as well as  for the other validations that we have  executed every time that we want to come  up with a child class now imagine how  hard that is going to be if for each of  the child classes that we will create in  the future we will have to go through  copying and pasting a third price and  quantity and as well as doing the  assigned to self objecting in those  three lines that is going to be a lot of  duplication of code now to save us that  time that is exactly why we need to use  the super function the super function  will allow us to have the attributes  access from the parent classes and  therefore we will be able to fully  implement the best practices in  inheritance when it comes to  object-oriented programs now again this  program works because we assign the  attributes of name price in quantity for  the self object in the child class but  if i was to remove  those  three lines and as well as those two  lines now those lines are happen to be  the lines that i have copied and pasted  and try to run this program then you can  see that we receive attribute error  phone object has no attribute price and  pay attention from what line it comes  from it comes from line 21  from the item class because it thinks  that it has the attribute of price but  we never have the price attribute in the  phone level because we just deleted the  self.price is equal to price and that’s  why  now we have some problems and we are  going to replace all the lines that we  have deleted with the following thing  that i’m going to just execute now so  i’m going to go to the first line of our  constructor and i’m going to say call  to super  function  to have access  to all attributes  slash methods and then i’m going to say  super  then i’m going to open up and close  parentheses and then i’m going to use  the double underscore init method like  that now you can see that the second  that i have completed this then there  are no more warnings about the  constructor in this child class and you  can also see that this double underscore  init method expects for some special  arguments now those special arguments  obviously coming from the item class  that we inherit from so if i was to pass  in here  name  and also  price and also quantity then this should  be fine now you can also ask yourself  isn’t it a duplication of code the fact  that we also copied and pasted the  parameters that we receive in the child  class and yeah that is a perfect  question that is something that could be  solved by something more advanced if you  heard about keyword arguments that is  something that we can solve it with that  way and then we will not have to  duplicate the parameters that we receive  for the constructor but that is not  something that i’m going to show for  that stage i’m going to stick with it  and i’m just going to leave it as it is  now  calling the super function and as well  as the init method right after it should  be responsible to have the same behavior  like we had previously so we should  still see 2  500 for this print line and we should  not see any errors and if i was to run  the program then you can see that we  receive the expected result so that way  we implement the best practices of  object-oriented programming for each  child class that we use a separated  constructor we also gonna need to call  the super function in order to have  fully access  for all the attributes and methods that  are coming from the class that we  inherit from all right so i minimized  the code for our classes and i also left  with one instance of phone here now i  want to show you the results of the  following things so i will say print and  i will see what is the list of all in  the item class is going to bring us back  so i’m going to say  and then i’m also going to say phone.all  if you remember we implemented this  class attributes as well here so i will  minimize the code back and then i will  run our program now you can see  something very weird in here we see item  and then we basically see the result of  the repr method that comes from the item  class now the reason that this happens  because we never implemented in our epr  method inside the phone class so that’s  why we see this ungeneric result of item  now you can also pay attention that we  only create an instance of the phone  class so that’s not so good that we see  item in those outputs so what we could  use instead of hard coding in the name  of the class in the repr method inside  the item class then we could access to  the name of the class generically now if  i was to replace this with some special  magic attribute that will be responsible  to give me the name of the class then  this will be perfect so i’m going to  delete that and i’m going to use curly  brackets and i’m going to say self  dot double underscore class  dot double underscore name so that is a  generic way to access to the name of the  class from the instance and by doing  this then besides receiving item hard  coded string then i should receive the  name of the class that i initialized  from the very beginning so this should  be  phone because that is the only single  instance that i have right now and you  can see that this is exactly the result  that i’m receiving back so that is  perfect now i said earlier that by using  the super function then we basically  have access to all the attributes and  the methods that are coming from the  class that we inherit from so what that  means it means that we will also have  the access to the class attribute of all  that is inside the item class and i’m  talking about  that attribute all right now to show you  that then i’m going to open back the  code from the phone class and i’m going  to remove the all attribute and i’m just  going to do that right now and i’m also  going to delete the actions to execute  where i use phone dot all dot append  because we no longer having the old  attribute in the phone class and if i  was to remove those and execute our  program now then you can see that i  still receive the same result so that is  a great idea removing the old attribute  in the child class level it is a great  idea to only use the old attribute in  the parent class because by using the  super function in the child class we  will have access to the old attribute so  this means that if one day would like to  have access to all the items instances  that have been initialized including the  child classes then accessing them from  item.all should also be enough now you  might be confused how this line is  responsible to add this instance inside  the all attribute that is happen to be a  list and that’s happening because by  using the super function and as well as  the init then we basically call the init  method inside the parent class now in  the latest line inside this method we  also use item.old.append  which is also going to be accessible  from the phone class so that’s why  calling the all  class attribute from the item class is a  better idea because it will give us the  complete picture okay so before diving  into the topic of that episode then  we’re gonna need to do some code  organization in here because as you can  see for each of the child classes that  we will go ahead and create in the  future to extend this project then we’re  going to need to do this in the main.py  file because that was the only single  file that we were working with and now  that our project grows we need to start  working with multiple files so that’s  why maybe working with a file that will  represent the class of item and working  with a separate file that will represent  the phone child class will be a better  idea so we will have the main.py file  dedicated for only creating instances of  those classes so let’s get started with  this so i’m going to go to the project  directory and create two python files  first one we will named item.py  the other one should be named phone.py  and i’m going to take the code from our  item class  and i’m just going to grab everything  like the following and i’m going to cut  this and then i’m going to paste this in  inside of that now pay attention that i  use the csv library so that’s actually  the location that i need this library so  i’m going to  just copy the import line and that  should be good enough now i’m going to  do the same process for the  phone.py and i’m going to be copying  this into the phone.py file as well but  now this file needs to import the item  class because as you can see we got an  error here so we should say from item  import item like the following and the  errors should be gone and then in the  main.py file we can basically use this  file to only instantiate instances  meaning creating data that will  represent something to python so this  means that we can go ahead and import  the class from the item file  we can do the same  from the  phone file and then we can go ahead and  do the stuff that we used to do so we  can say item dot  install sheet from csv and to verify  that this works we can also say print  item dot all like that  and if we want to run this file now to  see that this works then we can do that  and you can see that everything works  just as expected now just a quick side  note i’m not going to rely too much on  the child class that we have created in  the latest episode to show the problems  that we’re going to solve in that  episode i’m going to rely  more on the item class so that it will  be easier to follow and we will not  complex things too much now that doesn’t  mean that i do not recommend using child  classes or something like that but it  will be just easier to show you the  cases that i’m going to show in the  parent class so that’s why for example i  deleted temporarily the import line of  the phone class and i just came up with  a random item instance that name is my  item and the price happened to be that  number i did not specify quantity  because we have a default value and now  after this line you can see that i  override this attribute by the string of  other item now the expected result is  not going to surprise anyone because we  see at the right time when we print this  attribute but we  might want to ask ourselves is that a  behavior that we always want what if we  want to restrict our users to change the  attribute of name once the name has been  set up in the initialization meaning in  that line well that’s something that we  might want to achieve for critical  attributes like the name of your  instances and in our case  the name of our item so what we could do  we could actually go ahead and create  read-only so-called attributes meaning  that we have only one opportunity to set  the name of our item and then we cannot  touch the value of that anymore so what  that means it means that we can set up  this in the initialization and we should  have errors if we try to override the  value of that now that’s also known as  encapsulation when we talk about the  principles of object-oriented  programming which i will be focusing  more on the future episodes but now  let’s go ahead and see how we can come  up with read-only attributes how we can  restrict our users to override the  attributes after the initialization of  our instances  okay so on the left side we have the  main.py file and on the right side we  have the item.py file which we are going  to work on and inside the class i’m  going to create our first read-only  attribute now the way that you can start  doing this is by first using a decorator  and if you remember from the previous  episodes decorators are like functions  that you can pre-execute before another  function so i could go ahead and use the  property decorator and then go ahead and  create a function and here’s the exact  location that i could set up the name of  our read-only attribute so for testing  reasons let’s go ahead and call this  read-only name something in that kind  all right and then i will open up and  close parentheses and this will  obviously receive self because it’s  going to be belong to each of the  instances and now for testing purposes  let’s only go ahead and return a random  string like  a three times all right and then now  that we have done this i can go to our  main.py file and try to access this  property now pay attention that i’m  going to call those properties and not  attributes so i’m going to go here and  i’m going to try to  print item1 dot  name and now that i have wrote name pay  attention to the differences in this  drop down for read only name we receive  a totally different icon here on the  left side which stands for a property  where in here we see the f letter which  stands for a regular field so if i was  to try to print that and run our program  then obviously we will receive the  expected result but if i was to try to  set a new value for the read-only name  say that we want to change this to  something like that then you’re gonna  see that pycharm is going to complain  about this and even if we try to execute  that then we will end up with an  exception that says attribute error  can’t set attribute so that is how  read-only attributes so-called are  working in python you can create those  by using a property decorator before  your functions and return whatever value  you would like to return now the biggest  challenge here is going to be converting  the name attribute that we actually have  which is happen to be exactly here into  being a read-only attribute and that is  going to be a little bit challenging but  let’s go ahead and start working on that  so first things first i’m going to  delete those three lines because we are  not going to use this property anymore  and i’m going to scroll up a bit and  work underneath this constructor here so  you might think that converting the name  attribute into being read only meaning a  property is as easy as doing something  like  first using the property decorator and  then go ahead and say def name  then receive self as the parameter and  then use something like return self dot  name because we already have the self  type name assigned to the self object  but actually doing something like this  is like saying to that class hey from  now on you are going to have a name  attribute that is going to be read only  and that is straightforward the effect  of the property decorator so i’m going  to leave a comment here that is going to  look like the following but if you  remember  we try to set the self.name into a new  value inside our constructor so you can  see that this action is illegal because  we have a read only property here so  when you go ahead and create a property  with the name of basically name then you  are no more allowed to set this  value anymore you are only allowed to  have access to see this back in whatever  instance you will create so that is why  if i was to hover my mouse here then  we’re gonna see an error that is saying  property name cannot be set so the  pythonic way to doing this workaround to  get over this  is using one underscore before the name  of our actual attribute name that we  assign to the self object and by doing  this we earn a couple of things that are  quite important so first let me add here  an underscore and just use something  like that and then now i need to go to  my property function meaning the  property attribute and i’m gonna need to  add here the double underscore as well  because first things first i go ahead  and set up the value for my double  underscore excuse me single underscore  name into being equal to the  value of this parameter here and then i  go ahead and use one more read only  attribute that i intentionally give the  name of name and i and then i return  self dot underscore name now i can go  back to my main.py file and see what  effects those lines are having right now  on our instances so first i can go ahead  and set a name for my item and i can  access to the name of this item  by saying something like item one dot  name so i don’t really have to go ahead  and use item one dot underscore name  because that is going to be a little bit  ugly and not convenient because  accessing attributes with always an  underscore before is not nice for each  of the instances that you look to access  to their attributes doing this one time  inside the class is going to make it  okay but trying to access those  attributes outside of your class meaning  from the instances is not going to turn  it into too much pretty so that is the  best way to overcome such a thing and  now if i was to try to print that  then  excuse me let me fix that quickly by  item1 dot name  and run our program then you can see  that that is working and now let’s go  ahead and also see if we can set our  name into being equal to another  thing like that  see if that works you can see that i  cannot set that attribute but however i  can still see this underscore name from  the instance level and that is maybe  something that you look to avoid it  could have been a lot nicer if we could  somehow prevent totally the access from  this underscore name in here so the way  that this is achievable is by adding one  more underscore to the attribute name  now this might remind you something that  is called private attribute if you are  familiar with programming languages like  java or c-sharp that is pretty much the  same behavior of using the private  keyword before your attributes in those  kind of programming languages where it  has different principles when it comes  to object-oriented programming so to sum  up if you add one more underscore to  your attribute names meaning you use  double underscore then you basically  prevent the access to those attributes  totally outside of the class so let’s  see a simulation of that so i’m going to  minimize the terminal and i’m going to  go to my item.py file and besides using  here single underscore i’m going to add  one more and then i’m going to change  this to double underscore as well and  now if we were to go to our main.py file  and  let’s use here item one  dot and try to basically use  double underscore and try to access to  name now you can see that i don’t even  have an auto completion from my drop  down because i don’t have access to see  this attribute from the instance level  and that is something that you look to  achieve when you want to have a clean  read-only attribute and that is the way  that you can do that so if i was to try  to print this then that’s just going to  complain about how it does not have the  attribute of double underscore name  in this instance  and again if i was to remove those  double underscores then i will just  access it as a property meaning as a  read-only attribute and that is exactly  what i look to have here all right so  now that we got the idea of that then we  still might be curious about how to  set a new value for the name attribute  now obviously using the property  decorator is going to turn this into  being a read-only attribute but there  are still some decorators that will  allow you to however set a new value for  this  property of name so let’s see how that  is achievable so obviously that is not  going to work because it says  can’t set attribute so what we can do is  we can use a new method where we can  declare that we’d like to also set a new  value for this attribute that we named  name  so the way that that’s going to work is  by going to our class here and using  here one more method with a special  decorator now this decorator is going to  look like the following so i’m going to  refer to the  name because that’s the property name  and then i’m going to use the dot setter  so by doing this then i basically say  hey so i still want to set a new value  for that name although  that is a property meaning a read-only  attribute so now if i was to  go down and say something like def name  and this would receive self and as well  as one additional parameter because the  additional parameter should refer to the  new value that i want to set to that  name so i will receive a parameter that  i could name something like value and  then inside here i’m only going to set  the new value for our double underscore  name because if you remember  when an instance tries to see the value  of name then we basically return  self.double underscore name so when a  user will try to set the name again to a  new value then it should execute self  dot  name equals to value and by doing this i  basically allow our users to yet set a  new value for  name  so now let’s show what effect those  three lines are going to have in our  main dot py you can see that now the  error is gone i can now go down here and  use print item one dot name  and that’s going to work you can see  that i have other item so this means not  only i can set a new value for my  underscore name so-called  in the initialization i can also do that  later on if i only use this convention  in here now those getters and said this  thing are always confusing in no matter  programming language you work so i will  do a final summary of all what we have  learned until this point all right so  using add property  will basically give you a control of  what you’d like to do when you get an  attribute and also by using this then  you basically convert this attribute  into being read only if i was not  implemented  these setters in  here so you can see that now when i  commented those out then this line is  going to have some problems because by  not doing this then i basically say that  hey name is read only you cannot set  that if i want to again uncomment those  back then i will have the control to set  this attribute to whatever attribute i’d  like to now by using  this statement here basically getting  the attribute then i basically call the  bunch of codes that are being executed  in here so whenever i use item1.name  then python says to itself okay you try  to get that attribute so i will go ahead  and try to execute all the lines of  codes are  that are here so that is what exactly  happening here and to show you that then  i can just use a random print function  here that will say  you are trying to  get name like that then you should see  this line being printed right before  what the actual value is because at  first  we print you are trying to print the  name and then we return the self dot  underscore name so it prints that over  here so that is what happening when you  try to  get an attribute but when you try to set  an attribute then python says to itself  okay so here you try to set an attribute  so because you set an attribute then i  should go ahead and  execute the code that is inside here  because that is the setter of that  attribute so that is why when you go  ahead and  use this decorator then you should  always receive a parameter because the  other item is going to be passed as an  argument to that parameter it is very  important to understand that and that is  why i can only allow myself to use one  line of code that will say self dot  double underscore name  is equal to the new value that you try  to  set and to show you that again i can go  here and say print  you are trying  to set and this line should appear just  before this print line because  at first i try to set  a different value for name and then i  just print it back like that okay so if  i was to run that then you can see that  at first we see the line of you are  trying to set then right after it we  actually see whatever item one dot name  is equal to now the reason that the  value is set it is because we set it  over here and then the next time i try  to get the value then those lines are  getting executed so that is the life  cycle of getters and setters and that is  the way that it works by having the  control of whatever you’d like to do  when you set a new value you can also  restrict it you can go ahead and do some  conditioning or you can go ahead and  raise some exceptions if you don’t like  the value that you receive let’s say  that you want to restrict the length of  the characters for the name of that  attribute all right so that is something  that you can do you can actually go here  and say if  len  of the value  is um greater than 10  then you would like to raise exception  that will say  something like  your  the name is too long something like that  and then you can say  else and then you can execute the line  that will be responsible to set that  value so intentionally i’m going to  leave it as it is because the length of  that is  nine characters so we should not have  any arrows but if i was to add here  two more characters like that and  execute it then you can see that we are  going to receive an exception that will  say the name is too long so that’s how  ghettos and setters are working in  python you now have all the knowledge  that you need to play around with  different attributes and manage them the  way that you like to so i believe that  after the information that you received  in that episode you have everything that  you need to manage your attitude  successfully and play around with it and  as well as coming up with rich classes  that will have multiple attributes and  then you can set up special behaviors to  those attributes and also you can decide  that you’ll not like to force to receive  those attributes in the constructor you  can decide that you can delete some  parameters in your constructor and you  can say that you will not like to assign  those to the self object immediately  when you create an instance so whatever  you would like to you have all the tools  to play around with how to manage your  attributes object-oriented programming  comes with four key principles that you  should be aware of so you will  understand how you should design your  large programs so it will be easier to  keep developing it and i’m going to talk  about those principles which are  encapsulation abstraction inheritance  and polymorphism so the first principle  will be encapsulation and we will talk  about this a little bit so encapsulation  refers to a mechanism of restricting the  direct access to some of our attributes  in a program now notice how we did a  great job in the last part where we  implemented the encapsulation principle  on our project so pay attention to how  the name attribute could not be set to a  new value before it goes through some  conditions that we set here like the  length of the character being less than  10 characters so restricting the ability  to override the values for your objects  within your setters is exactly what the  encapsulation principle is about now to  even give you a better example of  encapsulation principle then we are  going to apply similar things to an  additional attribute which is going to  be the price attribute now if we take a  quick look in that program that i have  just executed  then you can already see that i have the  ability to directly set this object into  whatever number that i like to also  negative 900 will work here so that’s  probably something that we look to  change and the way that we can change  that is by implementing some methods  that will restrict the access to this  price attribute so it could have been  nice if we could have two methods that  will be responsible to increment this  price by some percentage amount and the  same goes for the discount now if you  remember we already came up with a  similar method that looks like apply  discount when we talked about class  attributes because self.pay rate  multiplied by the actual price  is actually going to change this  attribute being decreased by 20 because  pay rate is set to 0.8 if you remember  from the previous episodes so let’s go  ahead and continue designing this price  attribute to totally support the  encapsulation principle so first things  first i’m going to convert this price  into being a private attribute so it  will be a great start avoiding to set  this price directly like we have seen  previously now i’m not going to just add  here double underscore besides i’m going  to grab this whole thing  i’m going to  right click and then i’m going to say  refactor rename and then i’m just going  to rename this price by setting it like  that double underscore before that now  doing this is actually going to refactor  this change on the entire class where we  try to access the price attribute so  that is a great thing so we don’t really  have to change everywhere so once i have  done that then if we would also take a  look in the apply discount then you can  see that we have this being set to a new  variable name that we came up with so  now that we have done this then let’s go  ahead and create a property so we will  have the ability to access the price  attribute  temporarily being only read only so i’m  going to say add property and then i’m  going to say def  price  then i’m just going to return  self.  price so that’s a great starter to  restrict the access to the price  attribute because now we still have  access to the price attribute  and then we cannot set that so you can  see that if we were to try to access  item1.price  we will have some errors but we can just  access the  actual value of that where it comes from  the initialization so that’s a  oh actually i see that we hit an error  that says recursion error and that’s  probably because i did not add the  double underscore in here by mistake so  that’s actually a great exception that  we came across right now you can see  that we are going to hit recursion error  maximum recursion depth exceeded and  that happened because i tried to return  the price without the double underscore  so  if we try to call the self.price then it  is going to try to call this function  and if we try to return that then it’s  just going to loop over it again and in  some time it’s going to fail with the  recursion error as you see so that’s  actually a great exception that  we see now and if you see this exception  in your object-oriented programs now you  know how to handle it and if i was to  come back now to main and execute that  then you can see that the expected  result is here all right so now that we  have done this then let’s go back to our  class and try to work on our methods  that will modify the attribute of double  underscore price so i will actually cut  this method from here and i will just  put that  right under the property price that we  came up with so we will have a cleaner  look now first things first you can see  that we have the apply discount and we  will also like to come up with apply  um increments  like the following and we would like to  say here  self dot  double underscore price is equal to self  dot double underscore price  plus  self dot double underscore price  multiplied by some value that we can  receive as a perimeter so we could  actually receive a parameter  that we could name increment  value  and then we could just multiply it by  that number so now that we came up with  this then let’s test this up okay i’m  going to go back to my main.py and then  i’m going to call item1 dot apply  increment and then i’m just going to  pass in 0.2 so we will increment the  value of 750  by 20  now the next time that i access the item  one dot price  we should be able to see the actual  value of price which should be 900 and  if i was to run that then you can see  that the price has been incremented to  900 as expected so that is exactly  encapsulation in action because you go  ahead and you don’t allow the access  directly to the price attribute besides  you modify this attribute by using  methods like apply increment or apply  discount now the same will happen if i  was to now go ahead and use item1 dot  apply  discount and you can actually modify  this method in the way that you like to  but this currently refers to a class  attribute that we use  here so this should also again apply a  discount of 20 to the 900 price we  should be able to see 720  and that’s exactly what is happening  here all right so the next principle  that i’m going to talk about is called  abstraction now abstraction is the  concept of object-oriented programming  that only shows the necessary attributes  and hides the unnecessary information  now the main purpose of abstraction is  basically hiding unnecessary details  from the users now by seeing users i  basically mean people like me or you  that are going to use the item class to  create some item objects now you can see  that now we have a new program here that  has one item object that its name is my  item price being that number and we have  six from this item now you can also see  that i came up with a method that  doesn’t really exist which is called  send email so that method at the end of  the day should send an email to someone  that would like to decide about this  item and it will send info about how  much money we can earn by selling all  the items and maybe about some more info  that is related to this item now  sending an email is not as easy action  just by calling it with that way  because in the background email sending  has to go a lot of processes like  connecting to an smtp server and as well  as preparing the body of the email with  an auto message that will display some  info about this item so as we can  understand we have to go through a lot  of new methods before we go ahead and  just call a send email method so to  simulate that then i can actually go  ahead and say send email so i will just  create the method that is necessary  temporarily i will use pass now as i  said we also have to go through a lot of  other processes so it is a great idea to  create methods for each of those  processes like connecting to an smtp  server  smtp server like that and i will just  say pass because we only try to simulate  the idea of abstraction here i’m not  really going to send an actual email to  someone i’m just simulating an idea of  sending an email and we will also have  to go through preparing a body for an  automatic mail prepare  body right and then i can just return a  formatted string that will say  something like hello  um  someone  we could receive this as a parameter as  well and then we can say  we have  self.name  six times right so it should be six  self dot quantity times like that  then i can say regards  to shape code so that is just a very  simple email that we can send to someone  now you can understand that we have to  call those methods inside the send email  so simulating that will be self dot  connect  and then self dot  and  prepare body  and probably we also need to go through  sending it right so we can just  say something like send here  then use pass again now you can see that  those methods  at the end of the day are only going to  be called from the send email because  those are just parts of the email  sending process that is a bigger process  that we divided into multiple steps in  this class now the biggest problem is we  will have access  calling those methods  from the instance and that is exactly  what abstraction is about abstraction  principle says to you that you should  hide unnecessary information from the  instances so that is why by converting  those methods into being private methods  then we actually apply abstraction  principles and that is achievable in  python in a way which i’m going to be  honest is not too much convenient but it  is achievable by adding double  underscore now again in other  programming languages this is achievable  by having access modifiers for your  methods like private or public and i’m  talking about  programming languages like java c-sharp  etc so if we were to convert those  methods to private methods by only  adding double underscore then those only  could be called  from the class level meaning inside the  class so if we were to try to access it  then you can see that i’m going to have  auto completion meaning i will have the  ability to access those methods  and then i will just do the same for  the other methods now this error comes  from here because we did not really  specify some argument i’m just going to  add an empty string now if i was to go  back to our main.py file then you’re  gonna see that we are going to have some  troubles even if i’m going to try to  access it with a double underscore i’m  not even going to have an autocompletion  and the reason for that it is because  that is a private method so you really  have to think about your methods if you  want to make them accessible outside of  your class meaning from the instances  and that is exactly what abstraction is  about you want to abstract the  information that is unnecessary to call  it or to access it from your instances  okay so inheritance is the third  principle of object-oriented programming  inheritance is a mechanism that allows  us to reuse code across our classes now  that’s something that we have totally  designed well throughout this course  because we came up with more classes  that are child classes of the item class  where each child class represents a kind  of an item  now pay attention how i changed the  import line from  phone import phone and i use the child  class of item which we came up with  which is called phone you can see that  i’m passing similar arguments and i can  still use a code that is implemented in  the parent class if we were to execute  this program then we are not going to  receive any problems because  phone  uses all the methods and attributes that  it inherits from the item class which is  exactly here and if we remember we  designed the send email method in the  parent class and we can use it from the  instance of a phone and we can also do  that for the rest of the methods that we  came up with that really affects some of  the attributes like in the  encapsulation part where we applied  the apply increment method that receives  an increment value and if we were to  test this  incrementing the price by 0.2 and then  printing item one dot price then we  should see 1200 so if we were to print  that then you can see that that is  exactly the result so that is mainly  what inheritance is about it is about  reusing the code across all the classes  and that’s exactly the scenario here and  the beauty behind that is that you can  come up with more tried classes that  will represent kinds of items like  laptop keyboard camera everything that  you think about and then you can just  modify specific methods that you’d like  to according to the kind of item that  you have so that’s perfectly describing  what inheritance is about all right so  the last principle that we have now is  polymorphism now polymorphism is a very  important concept in programming it  refers to use of a single type entity to  represent different types in different  scenarios now a perfect example for this  definition will be some of the functions  that we already know that exist in  python now just a quick side note  polymorphism refers to many forms poly  being many and morphism being forms so  again the idea of applying polymorphism  on our programs is the ability to have  different scenarios when we call the  exact same entity and an entity could be  a function that we just call now as you  can understand polymorphism isn’t  something that is specifically applied  to how you create your classes that is  actually something that refers globally  to your entire project and in the next  few minutes we are going to see some bad  practices where polymorphism is not  applied and we are also going to see  where in python polymorphism is  perfectly applied so a great example of  where polymorphism is applied is in the  lan built-in function because the lan  built-in function in python knows how to  handle different kinds of objects that  it receives as an argument and it  returns you a result accordingly so as  you can see in here if we were to use  the land built-in function in a string  then we will receive the total amount of  characters but if we will do this in a  list then we will not receive the length  of characters of this entire expression  in here besides we will receive back the  amount of elements that are inside this  list and to show you how this is going  to work then i’m just going to run this  program and for sure the results are  just as expected so as the definition of  polymorphism says it is just a single  entity that does know how to handle  different kinds of objects as expected  all right so now that we understood that  the polymorphism is applied everywhere  in python especially in the land  building function let’s also understand  where it is implemented on our project  here now you can see that i try to call  the apply discount method that is never  implemented inside the phone class and  the fact that i can use it from the item  class it is because we inherit from this  class and that is the basically reason  now if i was to go back to that main dot  py file and run this then you can see  that that is going to work because the  applied discount is a method that i can  use from the inherited item class now  that’s exactly where polymorphism is  also in action because polymorphism  again refers to one single entity that  you can use from multiple objects now if  i was one day to go ahead and create  more kinds of items meaning more classes  that will represent different kinds of  items and from them to call the applied  discount method that’s also going to  work because the applied discount is a  method that is going to be accessible  from all the kinds of objects so that’s  exactly why you might have heard about  the terms of inheritance and  polymorphism together combined now to  show you that then let’s try to create  one more class that is going to be  identical to the phone class right i’m  going to create a keyboard file and then  i’m just going to say here  class  you know what before that let’s go to  phone  and  copy everything from here and paste this  in like that i’m going to get rid from  those lines  and i’m just going to leave the init as  it is i’m going to change the class name  from  phone to keyboard and i’m also going to  delete that attribute that we don’t need  broken phones all right so now that we  have this then i can actually go ahead  to my main.py file and use one more  import line that will say from  keyboard import keyboard and then i’m  going to change this to keyboard  will replace this name just to make it  more realistic then i’m going to run the  same program  you can see that this works so that’s  again exactly where polymorphism is in  action because we can use this single  entity from different kinds of objects  and it will know how to handle it  properly now by saying handle it  properly then i basically mean you can  have the control of how many amount of  discount you want to apply inside your  classes now because if we were to go to  keyboard and use a class  attribute exactly like we used in the  item class which was  pay rate then we’re going to have full  control for all the discounts that are  going to apply to the keyboard and to  show you that i’m going to attempt  typing in pay rate and you can see that  i even have auto completion because  overriding in the child class that is  legal all right so i can just say pay  rate is equal to 0.7 and that will be it  now i have the same discount amount for  all my keyboards if i was again to run  the main.py file then you can see that  the results are just as expected we see  700 so that is the beauty behind  inheritance and polymorphism together  and the same will go for sure if we were  to decide that we’d like to have 50  discount so it will only take from me to  go ahead and say pay rate is equal to  0.5 and that’s it so i hope that you  understand about polymorphism a bit  better now now just a quick side note  polymorphism is perfectly could be  implemented by using abstract classes  and that is just the identical way of  using interfaces in other programming  languages like java interface is a way  that you can implement how a class  should be  designed right so it is like a template  for a class and that is achievable by  using abstract classes which i’m not  going to cover in that part but again  polymorphism like i said is a term that  is implemented in different areas in the  whole python programming language so i  hope you had a great time learning the  object-oriented programming course now  you have a lot of tools that you can go  ahead and try to implement by yourself  on your projects which will really help  you to take you to the next step as a  developer see you next time   

admin

Leave a Reply

Your email address will not be published. Required fields are marked *