A GENTLE INTRODUCTION TO PYTHON CLASSES FOR NEWBIES

oluchi

Oluchi Orji

Posted on January 10, 2020

A GENTLE  INTRODUCTION TO PYTHON CLASSES FOR NEWBIES

Python is an object-oriented programming language (OOP), it is a very popular programming paradigm and is one of the most effective approaches to writing software.

Almost everything in Python is an object, with its properties and methods. So when solving real-world challenges, you create objects based on classes which are also known as instantiation(instances).

Class is defined as an object's blueprint or description and it is created with the keyword class.

Let me illustrate what a class looks like.

Create a class named Cake, so what do you know about cakes, you know we use flour to make the dough and an oven to heat the dough.
So we create an attribute named flour and oven.
When we want to bake a cake, we preheat the oven and mix our flour with other ingredients, so we create a method called preheat_oven and mix_dough.

class Cake:
    def __init__(self, flour, oven):        
        """Initialize attributes."""
        self.flour = flour
        self.oven = oven

    def preheat_oven(self):
        """create a method"""
        return f"Pre-heat {self.oven} to 350 degrees"
    def mix_dough(self):
        return f" Mix together {self.flour}, cocoa powder, baking powder" 

Now that our Cake class is created, we would create an object(instance) of the class called pound_cake.

pound_cake = Cake()

There’s a lot I have done here, but don’t worry I will break it down with the post.

1. The init() Method

All classes have a function called init(), which is always executed when we create a new instance based on the class and it is used to assign values to object properties, as the example above, we used init () function to assign values for oven and flour.
Whenever we want to make an instance from the Pizza class, we’ll provide values for only the last two parameters flour and oven.

2. The self Parameter

The two variables defined (oven and flour) each have the prefix self.
i. Any variable prefixed with self indicates the variable is available to every method in the class.
ii. It is used to access variables that belong to the class.

3. Methods

Classes can have methods defined in order to add functionalities.
Methods are functions that belong to the object.
Remember all methods have self as their first parameter

def preheat_oven(self):
    pass

4. Accessing attributes and calling methods.

To access the attributes of an instance, you use dot notation.
We created an instance of the Pizza class called pound_cake, so in order to access attribute flour, we do the following.

pound_cake = Cake("wheat flour","oven")
print(pound_cake.flour)
wheat flour

After we created an instance from the class Cake, we can use dot notation to call any method defined in Cake.

print(pound_cake.preheat_oven())
print (pound_cake.mix_dough())

#We can also create multiple instances too
sponge_cake =Cake('pastry flour', 'Roaster oven')
chiffon_cake = Cake ('whole wheat flour', 'Roaster oven')
print(chiffon_cake.mix_dough())

Pre-heat oven to 350 degrees
 Mix together wheat flour, cocoa powder, baking powder
 Mix together whole wheat flour, cocoa powder, baking powder

5. Modifying an Attribute’s Value through a Method

It can be helpful to have methods that update certain attributes for you. Instead of accessing the attribute directly, you pass the new value to a method that handles the updating internally.

Write a class that allows users to choose their favorite pizza toppings and favorite crust type from a pizza app.
Now the store is running a promo when you order a Margherita pizza, you can order a free drink.

Modify the drink attribute through the order_margherita method

class Pizza:
    def __init__(self, veggies, toppings, crust, oil):
        self.veggies = veggies
        self.toppings = toppings
        self.crust = crust
        self.oil = oil

    def order_margherita(self, drink):
        """modify attribute value here"""
        self.drink = drink
        return f"You ordered for {self.crust} pizza with the {self.veggies},{self.toppings},{self.oil} toppings and you have gotten a free {drink}"



margherita_pizza = Pizza( "tomatoes", "mozzarella" ,"thick" ,"extra virgin olive oil.")
print(margherita_pizza.order_margherita("coke"))

You ordered for thick pizza with the tomatoes, mozzarella, extra virgin olive oil. toppings and you have gotten a free coke.

6. Assigning a Default Value for an Attribute

When you assign a default attribute value, you don’t have to include a parameter for that attribute.

Still using our Pizza class, let me assign a default value for meat attribute and diary.

class Pizza:
    def __init__(self, veggies, toppings, crust, oil):
        self.veggies = veggies
        self.toppings = toppings
        self.crust = crust
        self.oil = oil
        self.meat = "beef"
        self.dairy = "cheese"

    def order_margherita(self, drink):
        """modify attribute value here"""
        self.drink = drink
        return f"You ordered for {self.crust} pizza with the {self.veggies},{self.toppings},{self.oil} toppings and you have gotten a free {drink}"

    def order_pepperoni(self):
        return f"You ordered {self.crust} pizza topped with {self.meat} and {self.dairy}"

order_pepperoni = Pizza( "chilli","oregano," ,"thin" ,"extra virgin olive oil.")
print(order_pepperoni.order_pepperoni())
You ordered thin pizza topped with beef and cheese

INHERITANCE

Inheritance allows us to define a class that inherits all the methods and properties of another class.

The parent class is the class being inherited from, also called a base class.
The child class is the class that inherits from another class.

The syntax looks like this

class ChildClass(ParentClass):
    pass

Create a child class named OrderPizza, which will inherit the properties and methods from the Pizza class

class OrderPizza(Pizza):
   pass

order_pizza = OrderPizza( "chilli","oregano","thin" ,"soya bean oil.") #create an instance
print(order_pizza.order_pepperoni())   #call a method

You ordered thin pizza topped with beef and cheese

Adding init() method and super() to a Child Class.

i. When you add the init() function, the child class will no longer inherit the parent's init() function,in order
to keep the inheritance of the parent's init() function, add a call to the parent's init() function:

class OrderPizza(Pizza):
    def __init__(self, veggies, toppings, crust, oil):
        Pizza.__init__(self, veggies, toppings, crust, oil)

pizza = OrderPizza( "tomatoes", "oregano" ,"thin","extra virgin olive oil.")
print(pizza.order_margherita("coca-cola"))

You ordered for thin pizza with the tomatoes, oregano, extra virgin olive oil. toppings and you have gotten a free coca-cola

ii. Python also has a super() function that will make the child class inherit all the methods and properties from its parent.

class OrderPizza(Pizza):
    def __init__(self, veggies, toppings, crust, oil):
        super().__init__(veggies, toppings, crust, oil)
pizza = OrderPizza( "tomatoes", "oregano" ,"thin","extra virgin olive oil.")
print(pizza.order_margherita("coca-cola"))
You ordered for thin pizza with the tomatoes,oregano,extra virgin olive oil. toppings and you have gotten a free coca-cola

Adding Attributes and Methods for the Child Class

Let’s add an attribute that allows the user to choose the delivery type and a method to order their pizza delivered.

class OrderPizza(Pizza):
    def __init__(self, veggies, toppings, crust, oil):
        Pizza.__init__(self, veggies, toppings, crust, oil)
        self.delivery="Bike man"
    def ride_confirmation(self):
        return f"A {self.delivery} will deliver your pizza in twenty minutes"

pizza = OrderPizza( "tomatoes", "oregano" ,"thin","soya oil")
print(pizza.ride_confirmation())
A Bike man will deliver your pizza in twenty minutes

CLASS AND STATIC METHODS

Class Methods

What we have looked at so far are self.attributes and methods.
The @classmethod decorator is a function decorator that instantiates an instance of a class using a different parameter(s) than those usually passed to the class constructor.
i. They are usually marked with a classmethod decorator and takes an implicit first argument ( cls )
ii. It doesn't return the instance of a class but a new object of the class cls.

An example below, maybe the Pizza startup wants to serve clients that are watching their sodium intake.

class OrderPizza(Pizza):
    def __init__(self, veggies, toppings, crust, oil):
        Pizza.__init__(self, veggies, toppings, crust, oil)
        self.delivery="Bike man"
    def ride_confirmation(self):
        return f"A {self.delivery} will deliver your pizza in twenty minutes"

    @classmethod
    def healthier_food(cls, vegetable):
        return f"Make me a {vegetable} salad"

order_salad = OrderPizza.healthier_food("parsley")
print(order_salad)
Make me a parsley salad

Static Methods

Static methods are similar to class methods except that they don't receive an implicit first argument.

i. They are usually marked with staticmethod decorator
ii. They behave like plain functions except that you can call them from the instance of the class.

An example below, maybe the Pizza store is out of bacon, it alerts the user to select another topping.

class OrderPizza(Pizza):
    def __init__(self, veggies, toppings, crust, oil):
        Pizza.__init__(self, veggies, toppings, crust, oil)
        self.delivery="Bike man"
    def ride_confirmation(self):
        return f"A {self.delivery} will deliver your pizza in twenty minutes"

    @classmethod
    def healthier_food(cls, vegetable):
        return f"Make me a {vegetable} salad"

    @staticmethod
    def order_bacon_pizza(topping):
        if topping == "bacon":
            return f"we don't have bacon in the store now, please choose another"
        else:
            return f"your pizza with {topping} is ready"

toppings = ["cabbage", "bacon","beef"]
for topping in toppings:
    pizza = OrderPizza.order_bacon_pizza(topping)
    print(pizza)
your pizza with cabbage is ready
we don't have bacon in the store now, please choose another
your pizza with beef is ready

YAY! 🙌 🎉🎉 We are almost done, let us test our Pizza class (you can test for the child class later).
The key to developing quality software is to test your code as you write it.

Create a new file (test.py) and add the following code below.

import unittest
from pizza import Pizza


class TestPizza(unittest.TestCase):
    """Tests for the Pizza class"""
    def test_make_marinara(self):
        pizza = Pizza("tomatoes", "oregano", "thin", "coconut oil.")
        pizza = pizza.make_marinara()
        self.assertIn('oregano', pizza)
        self.assertEqual(
            'You ordered for thin pizza with the following toppings tomatoes,oregano,coconut oil.',
            pizza)
        self.assertNotEqual("order a pizza", pizza)
        self.assertNotIn("cheese", pizza)

    def test_order_pepperoni(self):
        pizza = Pizza("tomatoes", "oregano", "thin", "coconut oil.")
        pizza = pizza.order_pepperoni()
        self.assertEqual('You ordered thin pizza topped with beef and cheese',
                         pizza)
        self.assertNotEqual("order a pepperoni pizza", pizza)


unittest.main()

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

I really hope you liked the article, please feel free to share your opinions about it, hopefully, I hope to recreate this in JavaScript.

References

  1. Python Crash Course by Eric Mathes
  2. Solo learn
  3. W3school

Let us connect Twitter | LinkedIn

💖 💪 🙅 🚩
oluchi
Oluchi Orji

Posted on January 10, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related