Skip to main content

Command Palette

Search for a command to run...

Dataraflow Week 2: An Insight Into Object-Oriented Programming

Updated
5 min read
Dataraflow Week 2: An Insight Into Object-Oriented Programming

Before gaining the opportunity to learn programming concepts from the Dataraflow organization, I had previously encountered object-oriented programming, and it was not an enjoyable experience. The idea seemed too complex in comparison to the rather straightforward Python syntax I had grown used to. However, this time it was a bit different because I had realized there was no escaping it. To transcend my limitations as a developer and ascend to the levels I hope to, I would need to understand object-oriented programming on a deeper level.

Object-oriented programming allows developers to structure their code for better reusability while providing a clear structure. Utilizing this concept when writing code translates

Classes, Objects, The __init__() and __str__() Methods And Their Applications

My lesson began with learning about classes and objects in Python, and how to initialize them. Classes and objects are the two core concepts in object-oriented programming, and are deeply intertwined with one another. A class defines what an object should look like, and an object is created based on that class. As such, when you create an object from a class, it inherits all the variables and functions from that class.

A class can be likened to the blueprints for a house, a design or template that defines the key features of said house. The number of bedrooms, the style of the roof, and the location of plumbing and wiring systems. On the other hand, the object is the tangible house that you can live in, which allows access to the features that were previously specified in the class. You can build many houses from the same blueprint, and each house is a unique instance of the class.

I also learnt about the __init__() method, which is always executed when a class is initiated. The method is used to assign values to object properties or perform other operations that are necessary when the object is created. The __str__() method, on the other hand, is used to control what is returned when the class object is represented as a string. Below is an example of code where I initialized a class A302, and an object persons, passing in attributes self.bunk1 and self.bunk2 into the class, then returning them inside the object.

class A302:
  def __init__(self, bunk1, bunk2):
    self.bunk1 = bunk1
    self.bunk2 = bunk2

  def __str__(self):
    return(f'{self.bunk1} and {self.bunk2}')

persons = A302('Mubbywilly', 'EmmaVic')
print(persons)

Inheritance of Class Properties and Methods

The inheritance of classes is a very important object-oriented programming concept. It describes a system in which a child class inherits all the methods and properties from its parent class. By calling the parent class when initializing the child class and utilizing the super() function, the child will possess all the methods and attributes of the parent class. However, an inherited method can be overridden by simply initializing a method of the same name in the child class, and more attributes can be added to the child class without interfering with the inherited attributes.

class LivingBeing:
    def __init__(self):
        pass
    is_alive = True

class Animal(LivingBeing):
    def __init__(self):
        super().__init__()
    canMove = True

class Bird(Animal):
    def __init__(self):
        super().__init__()
    def fly(self):
        print('The bird can fly')

bird = Bird()
bird.fly()
print(bird.is_alive, bird.canMove)

The __iter__() and __next__() Methods

I also learnt more about how custom methods are created in classes, and how the __iter__() and __return__() methods are used to create iterables and iterate through them. This concept was initially particularly tough for me to implement, but with time and patience to go through the motions over and over again, I was eventually able to grasp the concept and apply it in a Fibonacci class, which generated Fibonacci numbers up to a certain limit.

class Fibonacci:
    def __init__(self, n):
        self.lastNum = n
    def __iter__(self):
        self.firstNum = 0
        self.secondNum = 1
        return self

    def __next__(self):
        if self.firstNum <= self.lastNum:
            fibNum = self.firstNum
            self.firstNum, self.secondNum = self.secondNum, self.firstNum + self.secondNum
            return fibNum
        else:
            raise StopIteration

fibNums = iter(Fibonacci(100))
for x in fibNums:
    print(x)

Polymorphism of Functions/Methods/Operators & Python Scope

Polymorphism of functions, methods, and operators refers to the ability of a function, method, or operator to be utilized on different objects and classes. Python scope was also one of the topics that the program enlightened me on this week. The global scope refers to the main body of the Python code, to the local scope, which is restricted to the body of a function. As such, variables that are declared in the global scope are global, while those declared in the local scope are local variables. To update global variables in the local scope, the global keyword is used, and to update a local variable inside a nested function, the nonlocal keyword is used.

class Bird:
    def __init__(self):
        pass
    def speak(self):
        print('Chirp')

class Parrot(Bird):
    def __init__(self):
        super().__init__()
    def speak(self):
        print('Squawk')

class Crow (Bird):
    def __init__(self):
        super().__init__()
    def speak(self):
        print('Caw')
bird = Bird()
parrot = Parrot()
crow = Crow()

def make_bird_speak(a):
   a.speak()

make_bird_speak(parrot)  

#scope
def outer():
    message = "Hi"
    def inner():
        nonlocal message 
        message = 'How are you doing?'
    inner()
    print(message)
outer()

Capstone Project: Library Management System

All the concepts learned during the week culminated in a capstone project where I was required to create a Library system to manage books, members, and borrowing operations. The system was to support multiple types of books, track borrowed books, and allow iteration over members and books. The system should also demonstrate proper use of scopes and encapsulation. Below is just a sneak peek into the humble beginnings of the project, as the full version will be committed to my GitHub page once it is completed.

lass Library:
    def __init__(self, library_name):
        self.__library_name = library_name
        self.books = []
        self.members = []
    def __iter__(self):
        return iter(self.books)
    def __next__(self):
        for book in self.books:
            return book
    def getLibraryName(self):
        return self.__library_name

class Book:
    def __init__(self, title, author, year):
        self.title = title
        self.author = author
        self.year = year
    def getdescription(self):
        print(f'{self.title} by {self.author}, {self.year}')

More from this blog

DataraFlow Chronicles

13 posts