__init__, Self, And Types Of Variables In Python OOP: The Most Important

Hey Pythonistas, welcome back hope you’re having a great day. Let’s wise up👓 the day by discussing __init__, self, and types of variables in Python OOP.

Read this with care as these topics are as important❗ to OOP as food😋 is to a restaurant.

Here’s the code of the class we made in the previous post. Read it briefly as we would learn the above-mentioned topics from this class.

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}")
cust1 = Restaurant("John")

Done reading?

Let’s get started…

Previous post’s challenge’s solution

Before we jump🧗‍♀️ further into OOP here’s the previous post’s challenge’s solution:

class Account:
    def __init__(self, name, balance, password):
         self.name = name
         self.balance = balance
         self.password = password
 
    def withdraw(self, amt, password):
        # Check if the password is correct or not.
        if self.password != password:
            print("Incorrect password!")
            return None
        # Check if the amount is positive or not.    
        if amt<0:
            print("Can't withdraw a negative amount!")
            return None
        # Check whether the balance is present in the account or not.
        if amt>self.balance:
            print("Insufficient funds!")
            return None
        # If all checks passed decrease the balance.
        self.balance -= amt
        return self.balance
 
    def deposit(self, amt, password):
        # Check if the password is correct or not.
        if self.password != password:
            print("Incorrect password!")
            return None
        # Check if the amount is positive or not.    
        if amt<0:
            print("Can't deposit a negative amount!")
            return None
        # If all checks passed decrease the balance.
        self.balance += amt
        return self.balance
 
    def show_balance(self, password):
        if password != self.password:
            print("Incorrect password!")
            return None
        return f"Account Holder's name {self.name}\n Balance = ${self.balance}"   
John = Account("John", 2921, "I am John")
print("--------------------deposit method --------------------")
print(John.deposit(1000, "I am John"))
print("--------------------withdraw method --------------------")
print(John.withdraw(500, "I am John"))
print("--------------------show_balance method --------------------")
print(John.show_balance("I am John"))

Output:

--------------------deposit method --------------------
3921
--------------------withdraw method --------------------
3421
--------------------show_balance method --------------------
Account Holder's name John
 Balance = $3421

If you have read the previous post, well👍 then this should have been an easy-to-deal-with🤝 challenge.

This class is a lot like our Restaurant🏢 class. The difference is that the methods here return something instead of just printing.

And this has functionalities useful for banks🏦 whereas our class has functionalities useful for a restaurant🏢.

NOTE: I don’t add docstrings to functions when I am explaining them, ’cause you already know what’s happening. But it’s a great practice to add them to your functions.

The __init__ method: Constructor

In the previous post, we discussed objects and classes.

We also created our own class, the Restaurant🏢 class for our restaurant’s online services💻📱🌐.

Then we instantiated a cust1 object to see👀 how methods and variables inside of a class work👩‍💻 in relation🤝 to objects.

This worked well👍. The customer was able to see👀 the menu🍕🍿🧇☕, order stuff from it😋, and also make the payment💵.

Now it’s time⏳ that we see what that __init__() method was.

Ok so to easily understand it. Inside the __init__() method write📝 a print statement and run the code again.

def __init__(self,name):
    print("Welcome to our restaurant!")
    self.name = name #string
    self.order = [] #A list
    self.total_bill = 0 #A float value
#Creating an instance.
cust1 = Restaurant("John")

Output:

Welcome to our restaurant!

You didn’t add any print statements outside the class right?❓

Then what happened?🤔

This line is printed because of the print statement inside the __init__() method.

The __init__() method is a special method. It gets called whenever you instantiate an object from a class.

This method is called behind the scene even if it isn’t defined. It is the constructor🛠🧱 of a class.

You can imagine it as a cake🎂🥮 tray(class based on which cake will be baked). As soon as you pour the batter into the tray batter, that is, your cake(object of tray class) gets the shape and size according to the tray.

cake tray class example

Source: https://www.pinterest.com/pin/405253666468020306/

Similarly, when you instantiate an object from a class the __init__() method gets called and defines all the variables inside of it for the object.

It does this for all objects.

This is why you needed to give "John" (name) as an argument when you instantiated the cust1 object. It was a required argument for the __init__() method. And instantiating an object means the __init__() method is called.

I hope you got the point.

And by any chance, if not, read🧐 it again. Please🙏 do.

And if still there are any doubts🤔 in your head🧠 no matter how silly they seem to you ask them in the comment section below. Please🙏🙏 do that.

See👀 this is how the __init__() method in python functions.

Note:

  • Use the __init__() method to initialize the object’s attributes.
  • The __init__() doesn’t create an object but is automatically called after the object is created.
  • __init__()  is also called a constructor.

Here’s a fun fact🤣😅 there exists a lot of articles on the most famous🤩 waiter(s)!! on google!!. Yes, you read it, right, waiters🤷‍♀️. You can read one such article here.

Finally, moving on to the self keyword you must be freaking😠 out on this as well by now.

The self keyword

You are sincere and hardworking😤 given that fact💯, it’s sure that the customer who came to you, will recommend your restaurant to others as well.👏

Let’s say you got two new👩👩‍🦰 customers because of John’s👱‍♂️ recommendation. Create instances for both of them.

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}")
cust1 = Restaurant("John")
cust2 = Restaurant("Mary")
cust3 = Restaurant("Jenny")

Now, Mary ordered a coffee☕ and Jenny ordered a waffle🧇 and both of them paid the bill💵. The code for this would look like this:

cust2.place_order("coffee")
cust2.pay_bill()
print("----------------------------------------------------------------")
cust3.place_order("waffle")
cust3.pay_bill()

Output:

We are Placing Order please wait Mary...
Your is Order Placed successfully Mary!
Your order is:
['Coffee']
Your total bill amounts to $2.5
----------------------------------------------------------------
We are Placing Order please wait Jenny...
Your is Order Placed successfully Jenny!
Your order is:
['Waffle']
Your total bill amounts to $4

You would be like ok done👍. But what has this got to do with the self keyword?🤷‍♀️

Tell me did you tell the place_order() or the pay_bill() method that we are talking about Mary or Jenny?

I mean did you pass the customer’s name or variable as an argument?

No, right?❓

Then, how🤔 did these methods get to know which object is being mentioned?

Well, it is because of the self😎 you gave inside of the methods.

The self keyword passes the object as an argument behind the scene.

This means whenever you write object.method() the method takes the object as its argument because of the self keyword.

We need to put self before the variables related to objects because the self keyword lets python know that the variable belongs to objects of the class.

Here’s a visual explanation of how self helps methods:-

Code of Restaurant class by 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}")

It’s the same. Just for reviewing.

Types of variables

In OOP there are Three types of variables:

  • Instance/object variable,
  • Method/local variable, and
  • Class/static variable

A quick review of all three types of variables.

Instance/object variable

According to our Restaurant class, these would be the variables that are related to:

  • cust1,👱‍♂️
  • cust2, and👩‍🦰
  • cust3. 👩

These variables are defined inside the __init__ method of the class.

self.name, self.order and self.total_bill are both instance variables.

The value of instance variables varies🤹‍♂️ from object to object.

In simple language, each customer would give different orders🍕🧇☕, each one would have a different bill amount💵💴💷, and of course, will have different names🔖.

I think this was super easy for you and so would be the rest two.

Method/local variable

These are the variables defined inside any method of the class.

In our example, order in the place_order() and name in the __init__() are both method/local variables.

Note❗: I said(ok wrote) order not self.order and name not self.name

The scope of these variables is limited to the method.

If you try to use these variables outside the method then you’ll get your best friend😊: An Error❗.

Class/static variable

The class variables are neither associated with self nor defined inside of any methods.

These variables are defined inside the class.

It usually is created for values that are going to be common for all the objects.

In our example, the menu variable is a class/static variable. For, a car🚗 class, no_of_wheels = 4 could be a class variable because no matter how different all the cars will have 4 wheels.

The value of these variables does not change from object to object.

In short,

  • The instance variable –> inside __init__,
  • The local variable –> inside methods, and
  • The static variable –> common and inside the class.

Conclusion

We saw what is __init__() method with the help of the cake🎂 tray’s example.

Next, when John brought us to new👩‍🦰👩 customers we got introduced to the self keyword.

Lastly, with the help of our Restaurant class, we understood the three types of variables.

Hope you enjoyed learning✍ with me because I loved it.

Here’s a tip for you: while you are learning the OOP concept make a note at the end of each post. This note should simply consist of all the topics discussed in a manner you can understand.

A sample from my notes of the day:

Sample-notes

I’m sorry about my bad handwriting.😅

Challenge🧗‍♀️

Ok, so my paired programmers🤜🤛 the challenge for you today is to create a Library management class.

It might sound quite difficult to you.

Your library class should have 4 major functions.

One to show the books available in the library. Second to allow users to issue a book from the available books. Third to allow users to donate books to the library. Fourth to return the book that was issued by the user.

You are supposed to follow the following steps:

  • First, define a Library class.
  • Next, give it four methods:
    • list_books
    • issue_books
    • donate_books
    • return_books
  • Create an instance to test out all the functions.

You can use this string to make your library management class look better.

library_logo = '''
                   |```````````````|\\
                   |    Today      | |
                   |      A        | |
                   |    Reader   __|_|
                   |            |____|
                   |   Tomorrow    | |
                   |      A        | |
                   |    Leader     | |
                   |_______________|/
'''

To save time you can use these lists of books:

# 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"]

Hint:

class Library:
    library_logo = '''
                   |```````````````|\\
                   |    Today      | |
                   |      A        | |
                   |    Reader   __|_|
                   |            |____|
                   |   Tomorrow    | |
                   |      A        | |
                   |    Leader     | |
                   |_______________|/
    '''
    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):
        """prints the names of books available in the library.
        using self.bookList and for loop."""
    def issue_books(self, issuer, book_to_be_issued):
        """inputs the issuer and book_to_be_issued.
        checks whether the book is available in the library.
        checks whether taken by someone else(using the issueDict in the init)."""
    def donate_books(self, book_name):
        """inputs book and adds it to the booksList.
        And thanks the doner"""
    def return_books(self, book):
        """pops the book from the issueDict dictionary."""

You’ll truly have a fun time solving this challenge.

This was it for the post. Comment below suggestions if there and tell me whether you liked it or not. Do consider sharing this with your friends.

See you in the next post till then have a great time and enjoy your books 📚. Bye bye😊👋

Leave a Reply

This Post Has 14 Comments

  1. CB S

    It’s actually a cool and useful piece of info. I’m glad that
    you shared this helpful information with us.
    Please keep us up to date like this. Thanks for sharing.

  2. Maitry

    Thanks a lot for your kind words. Will definitely do my best to keep you all updated. Stay tuned…

  3. eTS

    Greetings from Colorado! I’m bored at work so I decided to check
    out your website on my iphone during lunch break. I love the information you present here and can’t wait to take a look when I get home.
    I’m shocked at how quick your blog loaded on my cell phone ..
    I’m not even using WIFI, just 3G .. Anyhow, fantastic blog!

  4. Maitry

    Thanks a lot. Stay tuned for more.

  5. zoritoler imol

    I truly appreciate this post. I?¦ve been looking everywhere for this! Thank goodness I found it on Bing. You have made my day! Thx again

  6. Maitry

    Thanks a lot. Glad you liked it. Stay tuned for more.

  7. z

    There’s noticeably a bundle to know about this. I assume you made sure good points in options also.

  8. Maitry

    Thanks!

  9. Twicsy

    Belo post, compartilhei com meus amigos.

  10. Maitry

    Thanks a lot!! Stay tuned…

  11. gothammag

    Hi there! Quick question that’s totally off topic.

    Do you know how to make your site mobile friendly?
    My website looks weird when browsing from my iphone.
    I’m trying to find a template or plugin that might be able to fix
    this issue. If you have any suggestions, please share. Cheers!

  12. Maitry

    If you are using WordPress Astra theme should work well. You can also check out phlox or oceanwp. Hope it helps.

  13. Aegean College

    I simply could not leave your website before suggesting that I actually loved
    the usual information an individual provide in your visitors?
    Is gonna be back continuously to investigate cross-check new
    posts

  14. Maitry

    Do visit! Lots of new stuff will be coming…