Object Oriented Programming using Python
Object-oriented programming
Object-oriented programming is a paradigm of programming that models software code after real-life objects. Just like objects, you can have instances of objects and objects can have attributes. Let's get into it.
Figure [1] - OOP |
Creating an object:
In the script above, we first defined a class Car, then instantiated Car class on variable 'car1' and we received the following output for our print statement.
<__main__.Car object at 0x0124E490>
This refers to the object stored at a particular memory location. We will see how to make this output more user friendly later on.
Adding attributes to an object:
All cars would have a make, model, and year of manufacture, so we can set those as attributes for our car1. In the script below, we have done just that.
Methods:
Say we want to ouput a simple print statement saying that a car has been added to the garage, we can do this using a 'method' as in the code below:
We add the 'self' argument here since Python passes the object itself as the first argument when it calls the methods. For example, when we call the method add_garage from the car1 instance, the car1 instance itself is passed to the method and this is represented by the 'self' argument. The output of the print statement looks like the following:
2016 Volkswagen Golf has been added to the garage.
__init__ method:
We need a set of rules to instantiate an object, we can do that by setting the '__init__' method. This 'init' method is called for every instance of the class.
We see the following output:
Car instance created.
Car instance created.
We can use this method to set up a Car instance such that every time it is called, we have a model, make, and year input.
The output for the above code looks like the following:
2016 Volkswagen Golf has been added to the garage.
Let's see what happens if we only enter the make and model:
The output:
Traceback (most recent call last):
File "c:\Users\user\Desktop\temp.py", line 10, in <module>
car1 = Car('Volkswagen', 'Golf')
TypeError: __init__() missing 1 required positional argument: 'year'
As we can see, we get an error saying that we missed a positional argument.
Input Validation:
Let's say that we want to assume that the year is 2022 if no specific model year is specified, then we can set a default value for the variable 'year' that can be over-written if required while calling the class object. Also, we can use the variables in the 'init' method anywhere in the class definition, so let's update the 'add_garage' method as well. The implementation for that looks like the follows:
Now, the output looks like the following:
2022 Volkswagen Golf has been added to the garage.
If we want to specify the object data type, for e.g., we want to make and model to be strings and year to be an integer. We can do that with a ':' operator. Also, since the first car model came out in 1886, we want 'year' to be greater than 1886, we can use an 'assert' statement for this. Let's take a look at how to how to implement this and what happens when we input an incorrect value:
The output looks like the following:
Traceback (most recent call last):
File "c:\Users\user\Desktop\temp.py", line 14, in <module>
car1 = Car('Volkswagen', 'Golf', 1885)
File "c:\Users\user\Desktop\temp.py", line 4, in __init__
assert year >= 1886, f"Model year {year} is not greater than 1886."
AssertionError: Model year 1885 is not greater than 1886.
As we can see, we now have an 'AssertionError'.
Class attributes:
So far we have seen instance attributes such as make, model, and year that are specific to every Car object but what if we have attributes such as the number of wheels that are common among all Car objects? In this case, we can use Class attributes.
From the example above, we see the output of '4' twice. For the instance attribute (car1.num_wheels), the value was obtained from the class definition.
Here's a special method to see all attributes (__dict__):
The output looks like the following:
{'make': 'Volkswagen', 'model': 'Golf', 'year': 2022}
{'__module__': '__main__', 'num_wheels': 4, '__init__': <function Car.__init__ at 0x021A9E38>, 'add_garage': <function Car.add_garage at 0x021A9DF0>, '__dict__': <attribute '__dict__' of 'Car' objects>, '__weakref__': <attribute '__weakref__' of 'Car' objects>, '__doc__': None}
Let's see how to call the class attribute in one of our instance methods.
Here the 'add_wheel' method takes the 'num_wheels' attribute from the class 'Car'.
The problem with this approach is that we will not be able to set num_wheels at the instance level to override the class level attribute, to overcome this, the best practice would be to use 'self.num_wheels' instead of 'Car.num_wheels'.
The output looks like the following:
[<__main__.Car object at 0x01ABE610>, <__main__.Car object at 0x01B2BA78>, <__main__.Car object at 0x01B2BA30>, <__main__.Car object at 0x01B50490>]
The output above shows us 4 car objects. This can be very useful, for e.g. if we would like to print all the car models, we can use the following code:
The output for which looks like the following:
Golf
XC90
911
R8
__repr__ method:
This method is similar to '__str__' method. So far, we have been seeing output such as '<__main__.Car object at 0x01ABE610>'. It would be more useful to return a string representing the object, we can do that using the following code:
Now, the output is much more user-friendly and looks like the following:
[Car('Volkswagen', 'Golf', '2016'), Car('Volvo', 'XC90', '2022'), Car('Porsche', '911', '2022'), Car('Audi', 'R8', '2022')]
It is also a best practice to return a string that represents our input string.
Conclusion:
Hopefully, this blog has presented a clear and concise understanding of Object Oriented Programming using Python. In a future blog, I hope to cover topics such as static and class methods, inheritance, getters & setters.
If you prefer to learn from a video format, I highly recommend the freeCodeCamp video (ref [4]) below. Thank you for reading!
---
References:
[1] https://www.udacity.com/blog/2021/11/__init__-in-python-an-overview.html#:~:text=The%20__init__%20method%20is%20the%20Python%20equivalent%20of,is%20only%20used%20within%20classes.
[2] Python special/magic methods -> https://www.tutorialsteacher.com/python/magic-methods-in-python
[3] https://docs.python.org/3/reference/datamodel.html
[4] Highly recommended -> https://www.youtube.com/watch?v=Ej_02ICOIgs&t=1960s&ab_channel=freeCodeCamp.org
[5] https://docs.python.org/3/tutorial/classes.html
Comments
Post a Comment