Checking Method Resolution Order (MRO) in Python

class Phone:
    def __init__(self, brand, model_name, price):
        self.brand = brand
        self.model_name = model_name
        self.price = price
        
    def full_name(self):
        return f"This phone is {self.brand} {self.model_name}"
    
    def make_a_call(self, number):
        return f"Dialling {number}..."

class Smartphone(Phone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera):
        super().__init__(brand, model_name, price)
        # Phone.__init__(self, brand, model_name, price)
        self.ram = ram
        self.internal_memory = internal_memory
        self.rear_camera = rear_camera

    def full_name(self):
        return f"This phone is {self.brand} {self.model_name} and it has a rear camera of {self.rear_camera}"

class Flagshipphone(Smartphone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera, front_camera):
        super().__init__(brand, model_name, price, ram, internal_memory, rear_camera)
        self.front_camera = front_camera

    def full_name(self):
        return f"This phone is {self.brand} {self.model_name} and it has a front camera of {self.front_camera}"
    
S1 = Smartphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP")
S2 = Flagshipphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP", "32MP")
print(S2.full_name())
print(help(Smartphone))

Output :

Help on class Smartphone in module __main__:

class Smartphone(Phone)
 |  Smartphone(brand, model_name, price, ram, internal_memory, rear_camera)
 |  
 |  Method resolution order:
 |      Smartphone
 |      Phone
 |      builtins.object
 |  
 |  Methods defined here:
 |
-- More  --

Multilevel Inheritance and Method Overriding in Python

class Phone:
    def __init__(self, brand, model_name, price):
        self.brand = brand
        self.model_name = model_name
        self.price = price
        
    def full_name(self):
        return f"This phone is {self.brand} {self.model_name}"
    
    def make_a_call(self, number):
        return f"Dialling {number}..."

class Smartphone(Phone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera):
        super().__init__(brand, model_name, price)
        # Phone.__init__(self, brand, model_name, price)
        self.ram = ram
        self.internal_memory = internal_memory
        self.rear_camera = rear_camera

    def full_name(self):
        return f"This phone is {self.brand} {self.model_name} and it has a rear camera of {self.rear_camera}"

class Flagshipphone(Smartphone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera, front_camera):
        super().__init__(brand, model_name, price, ram, internal_memory, rear_camera)
        self.front_camera = front_camera

    def full_name(self):
        return f"This phone is {self.brand} {self.model_name} and it has a front camera of {self.front_camera}"
    
S1 = Smartphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP")
S2 = Flagshipphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP", "32MP")
print(S1.full_name())
print(S2.full_name())

Inheritance in Python (2nd Method)

class Phone:
    def __init__(self, brand, model_name, price):
        self.brand = brand
        self.model_name = model_name
        self.price = price

    @property
    def full_name(self):
        return f"This phone is {self.brand} {self.model_name}"
    
    def make_a_call(self, number):
        return f"Dialling {number}..."

class Smartphone(Phone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera):
        Phone.__init__(self, brand, model_name, price)
        self.ram = ram
        self.internal_memory = internal_memory
        self.rear_camera = rear_camera
    
S1 = Smartphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP")

print(S1.full_name)

Inheritance in Python (1st Method)

class Phone:
    def __init__(self, brand, model_name, price):
        self.brand = brand
        self.model_name = model_name
        self.price = price
        
    @property
    def full_name(self):
        return f"This phone is {self.brand} {self.model_name}"
    
    def make_a_call(self, number):
        return f"Dialling {number}..."

class Smartphone(Phone):
    def __init__(self, brand, model_name, price, ram, internal_memory, rear_camera):
        super().__init__(brand, model_name, price)
        self.ram = ram
        self.internal_memory = internal_memory
        self.rear_camera = rear_camera
    
S1 = Smartphone("OnePlus", "8 Pro", "75000", "8GB", "256GB", "64MP")

print(S1.full_name)

Using getter() and setter() in Python

class Laptop():
    discount = 10
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price

    def apply_disc(self):
        after_disc = self.p - (self.p * (Laptop.discount/100))
        return after_disc

    def apply_special_disc(self, disc):
        after_spcl_disc = self.p - (self.p * (disc/100))
        return 
    #using_getter
    @property    
    def price(self):
        return self.p
    #using_setter
    @price.setter
    def price(self, new_price):
        self.p = max(new_price, 0)

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)

L1.price = -40000
print(L1.price)

Implementing static method in Python

class Laptop():
    discount = 10
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price

    def apply_disc(self):
        after_disc = self.p - (self.p * (Laptop.discount/100))
        return after_disc

    def apply_special_disc(self, disc):
        after_spcl_disc = self.p - (self.p * (disc/100))
        return after_spcl_disc
    @classmethod
    def from_string(cls, string):
        brand, model, price = string.split(',')
        return cls(brand, model, price)
    
    def full_brand(self):
        return f"The name of the brand is {self.bn} {self.mn}"
    
    @staticmethod
    def intro():
        print("Welcome to Laptop Shop")

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)
L4 = Laptop.from_string('HP,MNOP,70000')

Laptop.intro()
print(L4.full_brand())

Class method as constructor in Python

class Laptop():
    discount = 10
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price

    def apply_disc(self):
        after_disc = self.p - (self.p * (Laptop.discount/100))
        return after_disc

    def apply_special_disc(self, disc):
        after_spcl_disc = self.p - (self.p * (disc/100))
        return after_spcl_disc
    @classmethod
    def from_string(cls, string):
        brand, model, price = string.split(',')
        return cls(brand, model, price)
    
    def full_brand(self):
        return f"The name of the brand is {self.bn} {self.mn}"

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)
L4 = Laptop.from_string('HP,MNOP,70000')

print(L4.full_brand())

Implementing class method in Python

class Laptop():
    count_instance = 0
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price
        Laptop.count_instance+=1 #counting the number of instances

    def apply_disc(self, disc):
        after_disc = self.p - (self.p * (disc/100))
        return after_disc
    
    @classmethod
    def countInstance(cls):
        return f"You have called {cls.count_instance} instances of class {cls.__name__}"

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)

print(L1.apply_disc(20))
print(Laptop.countInstance())

Counting number of instances of a class in Python

class Laptop():
    count_instance = 0
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price
        Laptop.count_instance+=1 #counting the number of instances

    def apply_disc(self, disc):
        after_disc = self.p - (self.p * (disc/100))
        return after_disc

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)

print(L1.apply_disc(20))
print(f"Number of instances called = {Laptop.count_instance}")

Using instance variable and class variable wisely in Python

class Laptop():
    discount = 10
    def __init__(self, brand_name, model_name, price):
        #initializing instance varaibles
        self.bn = brand_name
        self.mn = model_name
        self.p = price

    def apply_disc(self):
        after_disc = self.p - (self.p * (Laptop.discount/100))
        return after_disc

    def apply_special_disc(self, disc):
        after_spcl_disc = self.p - (self.p * (disc/100))
        return after_spcl_disc

L1 = Laptop('Lenovo', 'ABCD', 40000)
L2 = Laptop('Dell', 'EFGH', 50000 )
L3 = Laptop('HP', 'IJKL', 60000)

print(L1.apply_disc())
print(L1.apply_special_disc(45))