The Best Way to Understand Composition in Python: 5 Case Studies and Solution
Understanding and applying compositions in a short time
Introduction
Compositions; It is a programming technique used when establishing relationships between classes and objects. Understanding compositions is important in object-oriented programming. Compositions can be a good idea in Python and software language to make a particular structure dynamic. Because in this way, we fill the place of complex code blocks with more compact material.
Why Composition?
Through the compositions, we actually state the relationship between the two classes. And in this way, the code can be reused. This has a common similarity with the concept of inheritance. As a result, we obtain more complex structures by combining objects between different types.
What we need to understand with quality; is our ability to reach a clear decision thanks to the conformity with the definitions made about a class member. Values and methods are created about the breed, such as an apple is a fruit and a fawn being an animal. And the attributes and methods created for these main classes are exactly applied to the lower classes. After the application, the results are expected not to conflict with the upper class. Of course, this will save you from code repetitions.
In the composition, the code is reused by adding other objects to objects instead of inheriting properties, created methods between classes. And indeed, classes created by composition are more flexible than the structure created by heritage. This is because adding new features without changing the existing code structure is more effective.
So we can highlight three main points:
- One of the classes that exist in the composition is created from one (or more) examples of the others.
- We can also function in some aspects of a class without using all the properties of another class.
- It is possible to reuse code by adding objects to different objects.
Composit and Components Class
As we mentioned above, it becomes possible to encode in a complex relational structure with compositions. This happens when the Composite class can contain another Component class object.
Component Indicates the number of instances or valid range the Composite class will contain.
Now, we proceed to consolidate our knowledge through examples.
Example-1: Creating an annual salary between salary and staff classes
A workplace can determine how much an employee has to pay by defining the Salary class. However, this can also be expressed well with different parameters as an employee’s income. For example, for an employee with a monthly salary of 2600 €, the annual sum can be determined with a 12-month payment. We can add an additional parameter to this, like the annual bonuses. Then let’s run a function from the Salary class in the employee class and view the Total salary:
class Salary:
def __init__(self, monthly_income):
self.monthly_income = monthly_income
def get_total(self):
return (self.monthly_income*12)
class Employee:
def __init__(self, monthly_income, bonus):
self.monthly_income = monthly_income
self.bonus = bonus
self.obj_salary = Salary(self.monthly_income)
def annual_salary(self):
return "Total: " + str(self.obj_salary.get_total() + self.bonus) + ' €'
obj_emp = Employee(2600, 500)
print(obj_emp.annual_salary())
output:
Total: 31700 €
Example-2: Composing by putting different substances in a material
For this example, we need a Freezer class. We will fill different materials into our main class and then try to view them in an empty list, which we will first mark as blank. We will have only one class, but in this class, the functions of storing and displaying the material will solve our problem. Then:
class Freezer(object):
def __init__(self):
self._container = []
def store(self, obj):
self._container.append(obj)
def stuff(self):
return self._container[:]
deepfreezer = Freezer()
deepfreezer.store('fish')
deepfreezer.store('pea')
deepfreezer.store('meat')
deepfreezer.stuff()
output:
['fish', 'pea', 'meat']
Example-3: Composing types in the zoo
Our aim here is to make a composition process that will give how many zoo animal species are in the category of birds. For this, we will first create the animal class. We will then designate the two different bird species (Falcon and Parrots) into the bird category. And finally, we will print how many different bird species exist within the zoo class according to the data of the 3 separate classes we have identified above. According to this:
class Animal:
name = ""
category = ""
def __init__(self, name):
self.name = name
def set_category(self, category):
self.category = category
class Falcon(Animal):
category = "birds"
class Parrots(Animal):
category = "birds"
class Zoo:
def __init__(self):
self.current_animals = {}
def add_animal(self, animal):
self.current_animals[animal.name] = animal.category
def total_of_category(self, category):
result = 0
for animal in self.current_animals.values():
if animal == category:
result += 1
return result
zoo = Zoo()
falcon = Falcon("Falcon") #create an instance of the Falcon class
parrots = Parrots("Parrots") #create an instance of the Parrots class
zoo.add_animal(falcon)
zoo.add_animal(parrots)
print(zoo.total_of_category("birds")) #how many zoo animal types in the birds category
If you examine the code well, you will notice that we return the current_animals.values () function for category count. Here is the part we are interested in because we want to see types rather than the number of birds or animals.
Example-4: Composing personnel and address classes
Composing this structure will allow for deeper learning. In our example, a software firm wants to record basic information about job applications. Information such as name-surname-coding history and address of the person that is important for them here. And for this, we want to create a print out that we can compose by calling up common functions between the person class and the Address class as two separate classes.
We want the sub-functions to include the display function basically in the person class. So let’s do:
class Personal:
def __init__(self,name,surname, programming_language, experience):
self.name=name
self.surname=surname
self.programming_language=programming_language
self.experience=experience
self.address=None
def View(self):
print(f"Personal Name & Surname: {self.name} {self.surname}")
print(f"Experience period: {self.experience} year")
print()
if self.address:
print("Address: ")
print(self.address)
print()
print("Programming Languages Used: ")
data_type=type(self.programming_language)
if data_type is str:
print(" - ", self.programming_language)
elif data_type is tuple or list:
for language in self.programming_language:
print(" - ", language)
else:
print("Error!")
print("")
print("-------------------------")
print("")
class Address:
def __init__(self, ad, district,city,land):
self.ad=ad
self.district=district
self.city=city
self.land=land
def __str__(self):
details=[self.ad]
if self.land:
details.append(self.land)
details.append(f"{self.district}/{self.city}")
return '\n'.join(details)
personal1 = Personal("Markus","Faber",("Python","PHP","Javascript","Java"), 18)
personal1.address=Address('Brienner St. 0123', 'Maxvorstadt','Munich',"GERMANY")
personal2 = Personal("Arim","Khandakar",("NodeJS","ReactJS"), 6)
personal2.address =Address('Rd No 456','Kalachandpur','DHAKA',"BANGLADESH")
personal3 = Personal("Julia","Gage",("Javascript","CSS"), 4)
personal1.View()
personal2.View()
personal3.View()
output:
Personal Name & Surname: Markus Faber
Experience period: 18 year
Address:
Brienner St. 0123
GERMANY
Maxvorstadt/Munich
Programming Languages Used:
- Python
- PHP
- Javascript
- Java
-------------------------
Personal Name & Surname: Arim Khandakar
Experience period: 6 year
Address:
Rd No 456
BANGLADESH
Kalachandpur/DHAKA
Programming Languages Used:
- NodeJS
- ReactJS
-------------------------
Personal Name & Surname: Julia Gage
Experience period: 4 year
Programming Languages Used:
- Javascript
- CSS
-------------------------
We created the __str__ method to make the address data look stylish. In the personal class, we first equated the address to ‘None’ and created it as a flexible variable. In this way, we made sure that the person who did not enter an address did not receive any errors.
Example-5: Composing clothes made of cotton materials by counting
Our last example is similar to the example of the products we placed in the freezer. This time, we will not look at the deep freezer, but maybe at our wardrobe. But here we want to count different types of clothing of the same material: Cotton shirts and trousers. This will also be an example of storage.
First of all, we will create a class that determines the name, material, and quantity of the product during the stocking phase. Each list will be set empty first. We will then define the functions in this class. The function of adding a product will then be a function of counting by the material. Then we will make variable assignments in the Shirt and Pants classes. And we will try to display products made from ‘Cotton’. Let’s do it:
class Clothing:
stock={ 'name': [],'material' :[], 'amount':[]}
def __init__(self,name):
material = ""
self.name = name
def add_item(self, name, material, amount):
Clothing.stock['name'].append(self.name)
Clothing.stock['material'].append(self.material)
Clothing.stock['amount'].append(amount)
def Stock_by_Material(self, material):
count=0
n=0
for item in Clothing.stock['material']:
if item == material:
count += Clothing.stock['amount'][n]
n+=1
return count
class Shirt(Clothing):
material="Cotton"
class Pants(Clothing):
material="Cotton"
formal = Shirt("Formal")
dress_pants = Pants("Dresspants")
formal.add_item(formal.name, formal.material, 13)
dress_pants.add_item(dress_pants.name, dress_pants.material, 7)
current_stock = polo.Stock_by_Material("Cotton")
print(current_stock)
output:
20
Conclusion
In Python, we tried to understand the methodology of Composition and gain practicality in practice. We have learned how to use the empty dictionaries and lists in the desired formats thanks to the attributes and variables assigned in sub-types of our initially empty classes. In this way, I hope with greater courage, an article has been formulated that will help you encode interclass composition.
Thank you for reading!