My Python Learning Journey: Week 4 - Steps I Took, Problems I Faced, and How I Solved Them.
Table of contents
- Hey everyone, in this week, I learned about the following Python concepts:
- These are the steps I took to grasp the concepts:
- These are the problems that I encountered:
- This is how I solved those problems:
- 1. Resolving Attribute Conflicts When Using @classmethod Decorator.
- 2. Common Inheritance Errors in Python's super() Calling Method.
- 3. Understanding the Difference Between __str__ and __add__ Methods in Python.
- 4. How to Add Two Objects in Python & Display the Result without __str__ method.
- These are the resources that helped me learn:
Hey everyone, in this week, I learned about the following Python concepts:
Inheritance: Single inheritance, Multiple inheritance, and Multilevel inheritance.
OOP Methods:
super()
method and@classmethod
.Advanced Concepts: The
@property
decorator and Operator Overloading in Python.
These are the steps I took to grasp the concepts:
Studied the basics of Single, Multiple, and Multilevel inheritance through Python examples.
Explored how to call a parent class's method using
super()
and why it’s useful.Learned the use of
@classmethod
for defining methods that operate on the class instead of an instance.Practiced with the
@property
decorator to replace traditional getters and setters.Wrote custom methods to make Python operators (like
+
,-
, and*
) work differently with user-defined objects.
These are the problems that I encountered:
Resolving Attribute Conflicts When Using
@classmethod
Decorator.Common Inheritance Errors in Python's
super()
Calling Method.Understanding the Difference Between
__str__
and__add__
Methods in Python.How to Add Two Objects in Python & Display the Result without
__str__
method.
This is how I solved those problems:
1. Resolving Attribute Conflicts When Using @classmethod
Decorator.
Problem: I encountered a problem where an instance attribute shadowed a class attribute, causing unexpected behavior i.e, When I set x.a = 10
, it created an instance attribute that overrode the class attribute, causing print(x.a)
to display the instance value while x.show()
still accessed the class attribute.
class Employee:
a = 5
@classmethod
def show(cls):
print(f"The value of a is: {cls.a}")
x = Employee()
x.a = 10
print(x.a) # Prints 10 (instance attribute)
x.show() # Prints 5 (class attribute)
Solution: To resolve this, I ensured the attribute always referred to the class-level value by using the class name to directly refer to the class attribute:
class Employee:
a = 5
@classmethod
def show(cls):
print(f"The value of a is: {cls.a}")
x = Employee()
x.a = 10
print(Employee.a) # Prints 5, always uses the class attribute
x.show() # Prints 5 (class attribute)
2. Common Inheritance Errors in Python's super()
Calling Method.
Problem: I encountered a TypeError
when using inheritance in Python. In the child class, I called super().__init__()
without passing the required arguments to the parent class, which caused this error:
class TwoDvector: # Parent class
def __init__(self, i, j):
self.i = i
self.j = j
def show(self):
print(f"The 2-D vector is: {self.i}i + {self.j}j")
class ThreeDvector(TwoDvector): # Child class (Inheritance)
def __init__(self, i, j, k):
super().__init__() # Error: Missing arguments for parent class
self.k = k
def show(self):
print(f"The 3-D vector is: {self.i}i + {self.j}j + {self.k}k")
b = ThreeDvector(5, 8, 7) # This will raise a TypeError
print(b.i, b.j, b.k)
b.show()
# TypeError: TwoDvector.__init__() missing 2 required positional arguments: 'i' and 'j'
Solution: To fix this, I passed the necessary arguments (i
and j
) to the parent class using super()
method.
class TwoDvector: # Parent class
def __init__(self, i, j):
self.i = i
self.j = j
def show(self):
print(f"The 2-D vector is: {self.i}i + {self.j}j")
class ThreeDvector(TwoDvector): # Child class (Inheritance)
def __init__(self, i, j, k):
super().__init__(i, j) # Pass i and j to the parent class
self.k = k
def show(self):
print(f"The 3-D vector is: {self.i}i + {self.j}j + {self.k}k")
b = ThreeDvector(5, 8, 7) # Now works correctly
print(b.i, b.j, b.k) # Output: 5 8 7
b.show() # Output: The 3-D vector is : 5i + 8j + 7k
3. Understanding the Difference Between __str__
and __add__
Methods in Python.
Problem:
- If we want to print only one object value i.e
print(v)
like in the below code then only usingdef __add__(self)
gives just a memory address, not the actual values.
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __add__(self):
return Vector(self.x + self.y + self.z)
v = Vector(7,8,10)
print(v) # Output: <__main__.Vector object at 0x000001AA02B96F90>
Solution: To print the value in a readable format, I need to use def __str__(self)
method.
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __add__(self): # Correctly adds two vectors
return Vector(self.x + self.y + self.z)
def __str__(self): # Used to return a string representation of the object.
return f"{self.x}i + {self.y}j + {self.z}k"
v = Vector(7,8,10)
print(v) # Output: 7i + 8j + 10k
4. How to Add Two Objects in Python & Display the Result without __str__
method.
Problem:
I observed that when trying to add two
Vector
objects and print the result.I expected that
print(v1 + v2)
would print the sum of the two vectors, and it worked correctly, but it was printing a string directly. This behavior didn't require the__str__
method.
Solution:
The key here is that the
__add__
method is returning a string directly, so it doesn’t need__str__
to display the result.Since
__add__
returns a string representation, Python automatically prints the result without needing the__str__
method.
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __add__(self, other): # Correctly add two vectors & return a string
return f"({self.x + other.x}i + {self.y + other.y}j + {self.z + other.z}k)"
v1 = Vector(7, 8, 10)
v2 = Vector(7, 8, 10)
print(v1 + v2) # This prints the sum of vectors without __str__ method.
# Output: (14i + 16j + 20k)