Basic Python Crash Course - Part 2
Python is an “Object Oriented Programming language” or OOP for short. It is a programming paradigm which focuses on reusable pattern of code, in contrast to procedural programming, which focuses on explicit sequenced instructions. When working on complex programs, object oriented programming let you reuse code and write code that is more readable, which in turn makes it more maintainable.
Table of contents
- Classes and objects
- Attributes and methods in class
- Instance attribute
- Class attribute
- Object inheritance
- Parent Vs Child class
1. Classes and objects
Class is kind of blueprint or a template for creating objects. Objects has variables and behaviour associated with them. In python a class is created by the keyword class
, similar to how we define functions by using the def
keyword.
An object is created using the constructor
of the class. This object will then be called the instance
of the class.
Instance = class(arguments)
2. Attributes and methods in class
A class is of no use if there is no functionality associated with it. Functionalities are defined by setting attributes, which act as containers for data and functions related to those attributes. Those functions are called methods.
For example a dog is a class and it has property like size, color etc. these are attributes of class dog and the behaviour or actions associated with class dog like running, eating, sleeping etc are methods of dog’s class.
Now lets create a simple class Dog
🐶 with no functionalities.
class Dog:
pass
tommy = Dog() #Instance of class dog
print(tommy)
## <__main__.Dog object at 0x0000000041AD0898>
Attributes :
You can define the following class with the name Dog
. This class will have attributes age
and name
.
class Dog:
age = 7
name = "Tommy"
You can assign class to a variable. This is called object instantiation. You will be able to access the attributes that are present inside the class using the dot operator.
For example in the Dog
example, you can access the attributes age
and name
of the class Dog
.
# instantiate the class Dog and assign it to variable tommy
tommy = Dog()
# access the class attribute age and name inside the class Dog
print(tommy.age)
## 7
print(tommy.name)
## Tommy
Methods
- Once there are attributes that “belong” to the class, you can define functions (methods) that will access the class attributes.
- When you define methods, you will need to always provide the first argument to the method with a
self
keyword. In this way the object gets passed to the methods.
class Dog:
age = 7
name = "Tommy"
def change_age(self, new_age):
self.age = new_age
def change_name(self, new_name):
self.name = new_name
Now instantiate this class Dog
with a variable tommy
.
tommy = Dog()
print(tommy.age)
## 7
print(tommy.name)
## Tommy
Here tommy
object gets passed to the methods change_age
and change_name
because the keyword self
was a parameter of the methods as defined in the Dog
class. The self
keyword ensures that the methods have a way of referring to object attributes.
#Change the age with the method change_age() and name by change_name().
tommy.change_age(10)
print(tommy.age)
## 10
tommy.change_name("jacky")
print(tommy.name)
## jacky
👉 Methods are like functions the only difference is that they belong in a given class/object/instance.
3. Instance attribute
You can also provide the values for the attributes at runtime. This is done by defining the attributes inside the __init__
method also known as constructor method. It is run as soon as an object of a class is instantiated.
Let’s take an below example
class Dog:
# constructor method
def __init__(self, age, name):
self.age = age
self.name = name
# method change_age
def change_age(self, new_age):
self.age = new_age
# method change_name
def change_name(self, new_name):
self.name = new_name
now you can directly define separate attribute values for separate objects. For example :-
tommy = Dog(7, "Tommy")
print(f"The age of dog is {tommy.age} and name is {tommy.name}")
## The age of dog is 7 and name is Tommy
tommy.change_age(10)
tommy.change_name("Jacky")
print(f"The changed age of dog is {tommy.age} and changed name is {tommy.name}")
## The changed age of dog is 10 and changed name is Jacky
Why self
keyword required while initializing attributes ?
self
is also an instance of class. Since instances of a class has varying values we could state Dog.name = name
rather than self.name
. But since not all dogs share the same name, we need to be able to assign different values to different instances. Hence the need for the special self variable, which will help to keep track of individual instances of each class.
👉 You will never have to call the
__init__()
method; it gets called automatically when you create a new ‘Dog’ instance.
4. Class attribute
Instance attributes are specific to each object, class objects are the same for all instances.
class Dog:
#class attribute
species = "mammal"
#Initializer/instance attribute or constructor method
def __init__(self,name, age): #name and age are instance attribute
self.name = name
self.age = age
So while each dog has a unique name and age, every dog will be a mammal.
5. Object inheritance
- Inheritance is the process by which one class takes on the attributes and methods of another.
- Newly formed classes are called child classes, and the classes that child classes are derived from are called parent classes.
- A child classes inherit all of the parent’s attributes and behaviors but can also specify different behavior to follow. (override or extend the functionality)
Lets take an example
Suppose we want to differentiate between different dogs we can choose breed for differentiation among different dogs.Since different breed of dogs behave differently.
# Parent class
class Dog:
# Class attribute
species = 'mammal'
# Initializer / Instance attributes
def __init__(self, name, age):
self.name = name
self.age = age
# instance method
def description(self):
return print(f"{self.name} is {self.age} years old")
# instance method
def speak(self, sound):
return print(f"{self.name} says {sound}")
# Child class (inherits from Dog class)
class Bulldog(Dog):
def run(self, speed):
return print(f"{self.name} runs {speed}")
# Child class (inherits from Dog class)
class Goldenretriever(Dog):
def run(self, speed):
return print(f"{self.name} runs {speed}")
Let’s create an instance of bulldog class
# Child classes inherit attributes and behaviors from the parent class
jacky = Bulldog("Jacky", 10)
jacky.description()
## Jacky is 10 years old
jacky.speak("howwwww")
## Jacky says howwwww
jacky.run("slowly")
# Child classes have specific attributes and behaviors as well
#print(jacky.run("slowly"))
## Jacky runs slowly
Let’s create an instance of Goldenretriever class
tommy = Goldenretriever("Tommy", 7)
tommy.description()
## Tommy is 7 years old
tommy.speak("bow-bow")
## Tommy says bow-bow
tommy.run("fast")
## Tommy runs fast
6. Parent vs child Class
class Dog:
species = 'mammal'
def __init__(self, name, age):
self.name = name
self.age = age
#instance method
def description(self):
return print(f"{self.name} is {self.age} years old")
def speak(self, sound):
return print(f"{self.name} says {sound}")
#child class
class Bulldog(Dog):
def run(self, speed):
return print(f"{self.name} runs {speed}")
class Goldenretriever(Dog):
def run(self, speed):
return print(f"{self.name} runs {speed}")
jacky = Bulldog("Jacky", 10)
jacky.description()
## Jacky is 10 years old
jacky.run("slowly")
## Jacky runs slowly
print(isinstance(jacky, Dog))
## True
julie = Dog("Julie", 12)
print(isinstance(julie, Dog))
## True
tommy = Goldenretriever("Tommy", 7)
print(isinstance(tommy, Bulldog))
## False
Both jacky and julie are instance of Dog()
class, while tommy is not an instance of Bulldog()
class.
👉 Objects can also have other objects that belong to them, each with their own methods and attributes.
bulldog.tail.wags() #bulldog an instance of dog has another object tail having method wags() associated with it.
bulldog.tail.type = "small" #bulldog an instance of dog has another object tail which has type attribute small
bulldog.head.mouth.teeth.canine.hurts() #bulldog has another object head which has another object mouth which has another object teeth which has another object canine which has method hurts().