Skip to main content

Nested Class / Inner Class in Python

 

Inner Classes

·         In Python, we can define a class inside another class, which is called an inner class.

·         An inner class can access the variables and methods of the outer class.

Example:

class OuterClass:

    def __init__(self):

        self.x = 5

 

    class InnerClass:

        def __init__(self):

            self.y = 10

 

outer_obj = OuterClass()

inner_obj = outer_obj.InnerClass()

 

print(inner_obj.y)  # Output: 10

 

In the above example, we have defined an inner class called InnerClass inside the outer class OuterClass. We create an instance of the outer class and then create an instance of the inner class using the outer class instance.

 

Nested Class

·         A nested class is a class that is defined inside another class, just like an inner class.

·         The difference is that a nested class is not dependent on the outer class, whereas an inner class is.

 

Example:

class OuterClass:

    def __init__(self):

        self.x = 5

    class NestedClass:

        def __init__(self):

            self.z = 15

nested_obj = OuterClass.NestedClass()

print(nested_obj.z)  # Output: 15

 

In the above example, we have defined a nested class called NestedClass inside the outer class OuterClass. We create an instance of the nested class using the syntax OuterClass.NestedClass(). We don't need to create an instance of the outer class before creating an instance of the nested class.

 

Inner Class Vs Nested Class

Inner Classes

  • An inner class is defined inside another class and can access the variables and methods of the outer class.
  • An instance of an inner class must be created using an instance of the outer class.
  • An inner class is used to logically group classes and can improve code organization and readability.
  • An inner class is dependent on the outer class and cannot exist without it.

Nested Classes

  • A nested class is defined inside another class but is not dependent on the outer class.
  • An instance of a nested class can be created without creating an instance of the outer class.
  • A nested class is used to logically group classes and can improve code organization and readability.
  • A nested class is not dependent on the outer class and can exist without it.

In summary, the main difference between inner classes and nested classes is their dependence on the outer class. Inner classes are dependent on the outer class and cannot exist without it, while nested classes are not dependent on the outer class and can exist independently.

 

Inner Class Example

 class Human:

    def __init__(self, name):

        self.name = name

        self.head = self.Head()

 

    class Head:

        def __init__(self):

            self.eyes = 2

            self.ears = 2

            self.nose = 1

       def introduce(self):

        print(f"Hello, my name is {self.name}. I have {self.head.eyes} eyes, {self.head.ears} ears, and {self.head.nose} nose.")

 john = Human("John")

john.introduce() # Output: Hello, my name is John. I have 2 eyes, 2 ears, and 1 nose.

 

In the above example, we have defined a Human class with an inner class Head. The Head class represents the head of a human and contains attributes for the eyes, ears, and nose.

 When we create an instance of the Human class, we also create an instance of the Head class and assign it to the head attribute of the Human instance.

 We can then use the introduce() method to introduce the Human instance and print out its name and the attributes of its Head instance.

 Note that we are accessing the attributes of the Head instance using the dot notation, i.e., self.head.eyes, self.head.ears, and self.head.nose. This allows us to access the Head instance from the Human instance using the head attribute.

 Examples:

 Create a class Person with a nested class Address. Address should have a constructor that accepts street, city, and state as arguments. Person should have a constructor that accepts name, age, and an instance of Address. Create an instance of Person and print its name, age, and address.

 class Person:

    def __init__(self, name, age, street, city, state):

          self.name = name

          self.age = age

          self.address = self.Address(street, city, state)

       

    def __str__(self):

          return f"Name: {self.name}\nAge: {self.age}\nAddress: {self.address}"

 

    class Address:

        def __init__(self, street, city, state):

              self.street = street

              self.city = city

              self.state = state

        def __str__(self):

              return f"{self.street},{self.city},{self.state}"

# Create Objects

person = Person("Gopal", 30, "49 MC Road", "Vijayawada", "AP")

 print(person)

 

Example2:

Create a class Bus with a nested class Engine. Engine should have a constructor that accepts horsepower and engine type as arguments. Bus should have a constructor that accepts make, model, and an instance of Engine. Create an instance of Bus and print its make, model, horsepower, and engine type. 

 class Bus:

    def __init__(self, make, model, engine):

        self.make = make

        self.model = model

        self.engine = engine

       

    def print_details(self):

        print(f"Make: {self.make}")

        print(f"Model: {self.model}")

        print(f"Engine Horsepower: {self.engine.horsepower}")

        print(f"Engine Type: {self.engine.engine_type}")

       

    class Engine:

        def __init__(self, horsepower, engine_type):

            self.horsepower = horsepower

            self.engine_type = engine_type

my_engine = Bus.Engine(200, "diesel")

my_bus = Bus("Volvo", "9700", my_engine)

my_bus.print_details()

The above code also can be used as follows:

class Bus:

    def __init__(self, make, model, engine):

        self.make = make

        self.model = model

        self.engine = engine

   def __str__(self):

        return f"Make: {self.make}, Model: {self.model}, Engine Horsepower: {self.engine.horsepower},              Engine Type: {self.engine.engine_type}"

   class Engine:

        def __init__(self, horsepower, engine_type):

            self.horsepower = horsepower

            self.engine_type = engine_type

 my_engine = Bus.Engine(200, "diesel")

my_bus = Bus("Volvo", "9700", my_engine)

print(my_bus)

 

Example 3:

Construct a class Bank with a nested class Account. Account should have a constructor that accepts account number and balance as arguments. Bank should have a constructor that accepts name and an instance of Account. Add a method deposit to Account that increases the balance by a specified amount. Add a method withdraw to Account that decreases the balance by a specified amount if sufficient funds are available. Create an instance of Bank and demonstrate how to deposit and withdraw funds from the account.

class Bank:

    def __init__(self, name, account):

        self.name = name

        self.account = account

    class Account:

        def __init__(self, account_number, balance):

            self.account_number = account_number

            self.balance = balance

       def deposit(self, amount):

            self.balance += amount

       def withdraw(self, amount):

            if amount > self.balance:

                print("Insufficient funds")

            else:

                self.balance -= amount

                print("Withdrawal successful")

my_account = Bank.Account("12345", 1000)

my_bank = Bank("My Bank", my_account)

print(f"Initial balance: {my_bank.account.balance}")

my_bank.account.deposit(500)

print(f"Balance after deposit: {my_bank.account.balance}")

my_bank.account.withdraw(200)

print(f"Balance after withdrawal: {my_bank.account.balance}")

my_bank.account.withdraw(2000)

Output:

Initial balance: 1000

Balance after deposit: 1500

Withdrawal successful

Balance after withdrawal: 1300

Insufficient funds

Exercises:      

  1. A restaurant wants to keep track of its menu items. Design a MenuItem class with a nested Ingredient class. The MenuItem class should have attributes for name, description, price, and a list of Ingredient objects. The Ingredient class should have attributes for name and quantity. Implement methods to add and remove ingredients, set and get attributes, and a method to display the details of a menu item with its list of ingredients.
  2. A company wants to manage its employees' information. Design an Employee class with a nested Payroll class. The Employee class should have attributes for name, age, and an instance of Payroll. The Payroll class should have attributes for salary and pay frequency. Implement methods to set and get the attributes, and a method to display the details of an employee with their payroll information.
  3. You are working on a system for a hotel that manages room reservations. Create a Room class with an inner class called Reservation. Each Reservation object should have a start date, end date, and a guest name. The Room class should have a method called is_available that takes a start and end date as arguments and returns True if the room is available during that period.
  4. You are developing a program that manages a library of books. Create a Book class with an inner class called Loan. Each Loan object should have a due date and a borrower name. The Book class should have a method called is_available that returns True if the book is not currently on loan.
  5. You are creating a program for a restaurant that allows customers to place orders online. Create a Menu class with an inner class called MenuItem. Each MenuItem object should have a name, description, and price. The Menu class should have a method called get_item that takes a name as an argument and returns the corresponding MenuItem object. The MenuItem class should have a method called order that adds the item to a customer's order and returns the total cost of the order so far.
  6. You are building a music player application that can play songs from a user's library. Create a MusicPlayer class with an inner class called Song. Each Song object should have a title, artist, and duration. The MusicPlayer class should have a method called add_song that takes a Song object and adds it to the user's library. It should also have a method called play_song that takes a title as an argument and plays the corresponding Song.
  7.  You are working on a program that manages a collection of board games. Create a BoardGame class with an inner class called Player. Each Player object should have a name and a score. The BoardGame class should have a method called add_player that takes a Player object and adds it to the game. It should also have a method called get_winner that returns the player with the highest score.
  8. You are developing a system for managing a school's course offerings. Create a Course class with an inner class called Student. Each Student object should have a name and a grade. The Course class should have a method called add_student that takes a Student object and adds it to the course roster. It should also have a method called get_average_grade that returns the average grade of all students in the course.
  9. You are creating a program for a coffee shop that allows customers to place orders. Create a Menu class with an inner class called MenuItem. Each MenuItem object should have a name, description, and price. The Menu class should have a method called add_item that takes a MenuItem object and adds it to the menu. It should also have a method called place_order that takes a list of MenuItem objects and returns the total cost of the order.

Comments

Popular posts from this blog

Python OOPs Concepts: Using Variables and Methods

  Types of Variables in OOPs Python   Instance Variable Static Variable Local Variable   Object Level Variables Class Level Variables Method Level Variables When to use: For Every Object if you want Separate copy, use Instance Variables For all object one copy is required, use static variables Inside method, Just used for temporary requirement Where to Declare Inside the constructor method (in general) Within the class directly, outside of methods (in general)   Within the method only. How to Declare Within the constructor: Instance variables can be declared within the constructor method using the self .   Using default values : Instance variables can be assigned default values during initialization.   Outside the class: use object name.   ·          Within the class directly

Polymorphism: Method Overloading vs Method Overriding

  Method Overloading In object-oriented programming languages, method overloading enables a class to have several methods with the same name but different parameters. However, in Python, method overloading is not directly supported as opposed to languages such as Java or C++. This is because Python allows developers to define default arguments for their methods and pass arguments of any type to a method. This flexibility allows a single method to handle various types of arguments, eliminating the need for overloading.   However, there is a way to simulate method overloading in Python by using default argument values or variable length arguments and conditional statements. Here's an example: Program using default arguments:       Program using variable length arguments:   Multiple methods with Same Name: When we define multiple methods with same name, Python will consider the last defined method only. Python will not support method overloading. ( Why? Method overlo

Inheritance

Inheritance is a fundamental concept in object-oriented programming, which allows a class to inherit properties and methods from another class. There are several types of inheritance, including: Single Inheritance: In single inheritance, a subclass inherits properties and methods from a single parent class. The subclass is said to be derived from the parent class. Multiple Inheritance: Multiple inheritance allows a subclass to inherit properties and methods from multiple parent classes. In this case, the subclass is said to have multiple base classes. However, multiple inheritance can lead to complexity and ambiguity in the code. Multilevel Inheritance: Multilevel inheritance occurs when a subclass inherits properties and methods from a parent class, which in turn inherits from another parent class. In this case, the subclass is said to be derived from both the parent class and the grandparent class. Hierarchical Inheritance: Hierarchical inheritance occurs when multiple subclasses