The 3 Types Of Methods And Inner Class In Python OOP

Hello Pythonistas, I hope🤞 you all are doing well.

Today we will discuss the concepts:- types of methods and Inner class.

We will continue the example of the Restaurant🏢 class we started in the last two posts to maintain consistency and clarity.

This is the current code in the Restaurant🏢 class that we have been working on till now:-

class Restaurant:
    menu = {"Pizza": 10, "Waffle": 4, "Coffee": 2.5}
    def __init__(self,name):
        self.name = name #string
        self.order = [] #A list
        self.total_bill = 0 #A float value
    def show_menu(self):
        print("Here's the menu of our restaurant:-")
        for item, price in self.menu.items():
            print(f"{item} ${price}")
    
    def place_order(self,order):
        print(f"We are Placing Order please wait {self.name}...")
        self.order = order.title().split(", ")
        print(f"Your is Order Placed successfully {self.name}!")
        print(f"Your order is: \n{self.order}")
    def pay_bill(self):
        if len(self.order)!=0:
            for i in self.order:
                if i in Restaurant.menu:
                    self.total_bill+=Restaurant.menu[i]
                else:
                    print(f"Sorry {self.name}, {i} is not available in this restaurant.")
        else:
            print("You need to Place order first!")
        print(f"Your total bill amounts to ${self.total_bill}")

Let’s take it further.

Before diving🏊‍♀️ into the post here’s the solution to the previous post’s challenge.

Previous post’s challenge’s solution

Here’s the code for your library📚 management system:-

from booksAndLogo import python_books, library_logo #I stored books and
#logo in a different file and imported them so the code is clean.
print(library_logo)
class Library:
    def __init__(self, list, name):
        self.booksList = list  #list of books available in the library 
        self.name = name  #name of the library 
        self.issueDict = {} #to store the books issued along with the issuer
    
    def list_books(self):
        print(f"\nThe following books are available in {self.name} library.")
        for book in self.booksList:
            print(book)
        print()
    def issue_books(self, issuer, book):
        """inputs the issuer and book.
        checks whether taken by someone else(using the issueDict in the init).
        If it is not then updates the issueDict.
        If it is then says its already taken."""
        if book not in self.issueDict.keys(): #keys() funciton provides list of all the keys in the dictionary.
            self.issueDict.update({book:issuer})
            print("Issue-Book database has been updated. You can take the book now")
        else:
            print(f"Book is already being used by {self.issueDict[book]}")
    def donate_books(self, book_name):
        """inputs book and adds it to the booksList.
        And thanks the doner"""
        self.booksList.append(book_name)
        print("Book has been added to the book list.\nThanks for donating.")
    def return_books(self, book):
        """pops the book from the issueDict dictionary."""
        if book in self.issueDict.keys():
            self.issueDict.pop(book)
            print(f"{book} is returned successfully.")
        else:
            print("Check again. No such books were issued.")
    
MyLibrary = Library(python_books, "python-hub.com")
MyLibrary.list_books()
MyLibrary.donate_books("my-python")
MyLibrary.issue_books("Me", "Think Python")
MyLibrary.return_books("Think Python")
print("------------------After using all the methods------------------")
MyLibrary.list_books()
  • list_books()📜
    • This method prints the books available in the library.
    • It uses an f-string to display the library name.
    • It uses the variables:
      • self.booksList
      • self.name
  • issue_books()🏷
    • This method checks if the book that is to be issued is already taken or not. The keys() function of the dictionary is used for this purpose along with the not in keyword
    • If the book is not already taken then the self.issueDict is updated using the update() function of the dictionary.
    • If it is taken then the method prints that the book is taken by XYZ.
    • It uses the variables:
      • self.issueDict
      • book
      • issuer
  • donate_books()🎊
    • This method inputs the book name and appends it to the self.booksList.It also thanks the user for donating.
    • It uses the variables:
      • self.booksList
      • book_name
  • return_books()🏷
    • This method checks if the book was issued or not.
    • If it was then the method pops it from the self.issueDict using the pop() function of the dictionary.
    • If it was not then the method tells the user to check the name again.
    • It uses the variables:
      • self.issueDict
      • book

After this, we created an instance of the library class named MyLibrary. Gave it a name and a list of books from our booksAndLogo module.

Then we simply tested all the methods using the MyLibrary instance of our class.

The booksAndLogo module:

# A Disclaimer: I haven't read the books mentioned below I just heard their names.
novels = ["THE GREAT GATSBY", 
          "THE ADVENTURES OF HUCKLEBERRY FINN",
          "TO KILL A MOCKINGBIRD", "THE CATCHER IN THE RYE",
          "LITTLE WOMEN", "MOBY-DICK", "CATCH-22",
          "INVISIBLE MAN",
          "THE OLD MAN AND THE SEA",
          "BELOVED"]
non_fiction = ["The Reluctant Carer",
               "Seven and a Half Lessons About the Brain",
               "The Sleeping Beauties",
               "How to Make an Apple Pie from Scratch",
               "Scary Smart",
               "The Psychology of Stupidity"]
finance = ["Rich Dad Poor Dad",
           "Money: Master The Game",
           "The Barefoot Investor",
           "The Intelligent Investor",
           "The One-Page Financial Plan",
           "The Little Book That Beats The Market",
           "Think and Grow Rich"]
sci_fi = ["FRANKENSTEIN",
          "BLAKE, OR THE HUTS OF AMERICA",
          "TWENTY THOUSAND LEAGUES UNDER THE SEA",
          "THE STRANGE CASE OF DR. JEKYLL AND MR. HYDE",
          "THE TIME MACHINE",
          "OF ONE BLOOD, OR THE HIDDEN SELF",
          "A PRINCESS OF MARS",
          "WE"]
book_series = ["The Chronicles of Narnia",
               "Twilight",
               "Harry Potter",
               "Goosebumps",
               "Perry Mason",
               "Choose Your Own Adventure",
               "Diary of a Wimpy Kid",
               "Noddy",
               "Star Wars",
               "Chicken Soup for the Soul"]
python_books = ["Python Crash Course",
                "Head-First Python",
                "Learn Python the Hard Way",
                "Python Programming",
                "Python Cookbook",
                "Fluent Python",
                "Invent Your Own Computer Games with Python",
                "Think Python",
                "Python for Kids",
                "Teach Your Kids to Code",
                "Python Tricks",
                "Effective Python"]
library_logo = '''
                   |```````````````|\\
                   |    Today      | |
                   |      A        | |
                   |    Reader   __|_|
                   |            |____|
                   |   Tomorrow    | |
                   |      A        | |
                   |    Leader     | |
                   |_______________|/
'''

This can turn out to be quite difficult for you. In that case, you should read the program from start to end. If it still seems difficult then go and read all the previous posts.

And the most important thing is to write the code yourself after you are clear with the logic.

I strongly suggest you read the previous posts on OOP to get clarity on the concepts.

Types Of Methods

There are mainly three 3️⃣ types of methods in Python OOP:

  • Instance method,
  • Class method, and
  • Static method.

The instance method deals🤝 with instance and local variables.

The class method deals🤝 with class variables.

And the static method has nothing👎 to do with class, instance, or local variables.

Let’s see👀 the syntax and use of all three methods.

Instance method

Like nitrogen is the most commonly found gas in the earth’s🌎 atmosphere, this type of method is usually found in Python OOP

Types of methods nitrogen example

The place_order() method in our Restaurant class is an instance method:

All the methods that we have used by now in our Restaurant class are instance methods:

def place_order(self,order):
    print(f"We are Placing Order please wait {self.name}...")
    self.order = order.title().split(", ")
    print(f"Your is Order Placed successfully {self.name}!")
    print(f"Your order is: \n{self.order}")

These methods either:

  • get, or
  • set

information/attributes about instances(objects).

So, we have getters and setters.

This method works👩‍💻 as both a getter and setter method. It sets the value of self.order. And it also gets the value of self.order.

In short, these types of methods deal🤝 with objects and their attributes. These methods usually have a self keyword.

Here’s an interesting thing, self is not a keyword but a convention in python. You can use any other name in place of self and your program will function well👍. But it is advisable👩‍🏫 to use self as it increases the readability of code and is a good✅ programming practice.

To avoid confusion😵 I introduced the self as a keyword to you. Hope you don’t mind🙂.

How to call an instance method

Code:-

You can call an instance method using an instance of the class. For example, you can call the place_order📝 method using cust1👱‍♂️ instance of the Restaurant🏢 class.

cust1 = Restaurant("John")
cust1.place_order("coffee, Waffle")

Output:-

We are Placing Order please wait John...
Your is Order Placed successfully John!
Your order is: 
['Coffee', 'Waffle']

Now let’s move on to the class method.

Class method

These are the methods that deal🤝 with class variables and details.

In our Restaurant🏢 class, we have set a class variable menu and have given it a dictionary as its value which contains items as keys and their prices as values.

As I have already mentioned in the previous post that accessing variables outside of the class isn’t a good practice.

We defined a show_menu() method to access the menu.

cust1.show_menu()

Output:

Here's the menu of our restaurant:-    
Pizza $10
Waffle $4
Coffee $2.5

But this is not how we should access a class variable even inside the class.

To make it correct we need to make the show_menu() method a class method.

For this, we need to use a decorators🎆🎇 @classmethod and a convention just like self which is cls.

@classmethod
    def show_menu(cls):
        print("Here's the menu of our restaurant:-")
        for item, price in cls.menu.items():
            print(f"{item} ${price}")

To define a class method you need:

  • A decorator: @classmethod. I’ll explain decorators in the upcoming posts. For now, using this is compulsory❗ to define the class method.
  • cls parameter. It is similar〰 to self. The difference is that self is used for instance methods and variables📝 whereas cls is used for class methods and variables🍕.

Syntax of class method:

@classmethod
def func_name(cls, other_arguments):
   #code to be executed

Did you notice🧐 that we used a cls before the menu variable inside the add_to_menu method?

It is because whenever you want to access a class variable inside the class it’s compulsory to use cls or the class’s name.

If you don’t, your buddy🤘 error❗ would be there:

NameError: name 'menu' is not defined

How to call a Class method

You can call a class method

  • either using the class’s instance or
  • using the class itself.

Code:-

cust1.show_menu()
Restaurant.show_menu()

Output:-

Here's the menu of our restaurant:-
Pizza $10
Waffle $4
Coffee $2.5
Here's the menu of our restaurant:-
Pizza $10
Waffle $4
Coffee $2.5

Time🕒 for the static method.

Static method

Don’t you think🤔 the customers should be welcomed when they come to your restaurant’s services👧👸?

Do you need to use a class or instance method for this?🤔

None of them, because you just want to print out the welcome🙏 statement.

The static method will help 🤝you here.

Let’s define a welcome method in our class:

@staticmethod
def welcome():
   print("Hello, welcome to the restaurant, how many people will be dining today?")

This is how you define a static method. You just need to use the @staticmethod decorators🎆🎇. There is no compulsion for parameters in this type of method.

It is used whenever you want to do something that has nothing to do with class or object but still needs to be in the class.

How to call a Static method

Code:-

cust1.welcome()
Restaurant.welcome()

Output:-

Hello, welcome to the restaurant, how many people will be dining today?
Hello, welcome to the restaurant, how many people will be dining today?

__init__()

You might be thinking🤔 I got the three types of methods. But, what about the __init__() method?

Well, the __init__() method is a special✨ type of method known as a constructor.

This method is called when an object is created from the class. It comes in none of the three categories.

Inner class / Nested class

NOTE: generally inner classes are avoided.

Now till this point, we have seen👀 that a class can have variables and methods inside of it.

The question is can we have a class inside a class?

Sounds weird😒 let’s understand this in detail.

Why Inner Class?

One customer used your restaurant’s online service instead of a veg pizza🥦🍕 they got a non-veg pizza🐔🍕.

Now you asked your employees why did it happen❓. They answered that it is because they get confused😵 as all orders veg🥛, non-veg🐔, or vegan🥦 were taken together.

At this, you might think of making separate classes for all three. That’s a good👍 idea no doubt. But we have something called inner class in python that can make you do it more clearly.

The reason for using an inner class, in this case, is that the restaurant needs all the varieties🥦🐔🥛. But without your restaurant class, varieties are of no use❌.

Just like every remote📱 needs a battery🔋 but a battery is useless without a remote. And like every car🚗 needs an engine but an engine is useless without a car.

Due to this reason, we will create a Vegan class inside the Restaurant class.

It will

  • make the code more readable🧐,
  • save your time🕒, and
  • will help in hiding the Vegan class from the outside world🌐.

That’s why we need inner classes.

We are not making all the 3 inner classes cause that would make the code and article super long and you’ll end up sleeping🥱😅. But you can have multiple🤹‍♀️ inner classes in your code for sure.

How to Make Inner Class?

Let’s define the Vegan🥦 class inside of the Restaurant class:

class Restaurant:
    menu = {"Pizza": 10, "Waffle": 4, "Coffee": 2.5}
    def __init__(self,name,veganR):
        self.name = name #string
        self.order = [] #A list
        self.total_bill = 0 #A float value
        self.veganR = self.Vegan(veganR)
    @classmethod
    def show_menu(cls):
        print("Here's the menu of our restaurant:-")
        for item, price in cls.menu.items():
            print(f"{item} ${price}")
    
    def place_order(self,order):
        print(f"We are Placing Order please wait {self.name}...")
        self.order = order.title().split(", ")
        print(f"Your is Order Placed successfully {self.name}!")
        print(f"Your order is: \n{self.order}")
        
    def pay_bill(self):
        if len(self.order)!=0:
            for i in self.order:
                if i in Restaurant.menu:
                    self.total_bill+=Restaurant.menu[i]
                else:
                    print(f"Sorry {self.name}, {i} is not available in this restaurant.")
        else:
            print("You need to Place order first!")
        print(f"Your total bill amounts to ${self.total_bill}")
    @staticmethod
    def welcome():
        print("Hello, welcome to the restaurant, how many people will be dining today?")
    class Vegan:
        def __init__(self,vegan):
            self.vegan = vegan #True or False
            if self.vegan:
                print("This food is Vegan.")

Here we simply defined a Vegan class inside the Restaurant class.

This vegan class has an __init__() method which inputs whether the order is vegan or not and if it’s vegan then prints it’s vegan.

How to use Inner Class?

There are 2✌ major ways to use the inner class:

  • Create an instance of the inner class inside the outer’s __init__()
  • Create an instance of the inner class outside the outer class

Let’s define a veganR variable inside of the __init__() of the Restaurant class. And use the Vegan class with the help of cust1 and cust2 instances of the Restaurant class:

def __init__(self,name,veganR):
    self.name = name #string
    self.order = [] #A list
    self.total_bill = 0 #A float value
    self.veganR = self.Vegan(veganR)
cust1 = Restaurant("John",True)
cust2 = Restaurant("Jenny",False) #It would give no output.

Output:-

This food is Vegan.

Now let’s create an instance outside the Restaurant class.

ve = Restaurant.Vegan(True)

Output:-

This food is Vegan.

Hope that you are clear with inner classes.

The inner class is a good feature of Python it is straightforward and enhances readability. Still, it isn’t a widely used feature.

And I know you might be thinking it’s a lame example of inner classes but trust me this would make them super easy for you when you use them, if you do of course.

Conclusion

We started🚀 this post by getting to know that the place_order()😋 method we were using was an instance method.

Here we also got to know that self is a convention✅, not a keyword❌.

Then we saw the way we defined our show_menu() method incorrectly❗. We corrected it by learning about class methods. We also came across decorators 🎆🎇 here.

Up next, we saw what are static methods. And we also got to know that __init__() method comes under none of the 3 categories.

Finally, to make our restaurant’s online services more efficient🤘 we defined an inner class Vegan☕🍕🧇 in it.

Challenge 🧗‍♀️

So your challenge is to make a Membership🙋‍♀️ class inside of the library📚 class you made in the previous post’s challenge.

It should have:

  • the member’s name, and
  • membership no.1️⃣2️⃣3️⃣

as instances variable.

And a class variable to store the names and membership no.s of all the members. (dictionary)📝

membership in library.

source: unsplash.com

With all of that and more, I’ll see you in the next post till then solve the challenge and have a great time. Bye Bye😊👋

Leave a Reply