My Python Learning Journey: Week 5 - 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. Use Case of Type Hints in Function Definitions: Auto-Suggestion of Methods:
- 2. Type Hints Error: Mismatch Between Declared and Actual Types:
- 3. Exception Handling Error: Catching the Wrong Exception Type:
- 4. Enumerate( ) Function Error: Forgetting to Unpack Tuple Values:
- 5. Walrus Operator Error: Misunderstanding Scope:
- 6. Importance of try-except-finally block inside User-Defined Functions while Handling Errors.
- These are the resources that helped me learn:
Hey everyone, in this week, I learned about the following Python concepts:
Type Hints.
Exception Handling.
if __name__ == “__main__”
Global Keyword.
Enumerate( ) Function.
List comprehension.
Newly Added Python Features: Walrus Operator
(:=)
and Match-Case Statements.
These are the steps I took to grasp the concepts:
I practiced type hints by rewriting my previous functions improving code readability & reducing errors.
Handled errors using
try-except
,try-except-else
, andtry-except-finally
blocks in small projects.Used the
if __name__ == "__main__"
condition to check if a Python file is being run directly or imported as a module.Worked with the
global
keyword to modify global variables inside functions.Solved problems with
enumerate()
functions to simplify loops.Practiced list comprehension to create lists using a single line of code.
Explored the walrus operator and match-case statements with examples from Python 3.8+
These are the problems that I encountered:
Use Case of Type Hints in Function Definitions: Auto-Suggestion of Methods.
Type Hints Error: Mismatch Between Declared and Actual Types.
Exception Handling Error: Catching the Wrong Exception Type.
Enumerate( ) Function Error: Forgetting to Unpack Tuple Values.
Walrus Operator Error: Misunderstanding Scope.
Importance of
try-except-finally
block inside User-Defined Functions while Handling Errors.
This is how I solved those problems:
1. Use Case of Type Hints in Function Definitions: Auto-Suggestion of Methods:
Problem: Beginners usually get confused by the use case of type hints, especially in function definitions.
Solution: By using type hints in function definitions, we can make our code editor smarter. Type hints not only act as documentation but also enable features like auto-suggestions, which reduces errors.
def concatenate(a: int, b: str):
# Example usage inside the function
result = b.upper() # IDE suggests methods related to 'str' for 'b'
return str(a) + result
output = concatenate(123, "hello") # Calling the function
print(output) # Output: "123HELLO"
When I typed
a.
inside the function, my editor suggested methods related to theint
type, such asbit_length()
andto_bytes()
.Similarly, when I typed
b.
, it suggested methods related to thestr
type, such asupper()
,lower()
, andreplace()
.This happens because type hints (
a: int
,b: str
) help the editor understand the types of the variables.
2. Type Hints Error: Mismatch Between Declared and Actual Types:
Problem: I encountered an issue when I declared type hints for a function but passed an argument of the wrong type, resulting in a runtime error.
def add_numbers(a: int, b: int) -> int:
return a + b
result = add_numbers(5, "10") # Passing an integer and a string
# Output: TypeError: unsupported operand type(s) for +: 'int' and 'str'
Solution: To solve this, I made sure that the arguments passed to the function matches with type hints. Additionally, I also added runtime checks to validate the input types.
def add_numbers(a: int, b: int) -> int:
# Validate input types
if not isinstance(a, int) or not isinstance(b, int):
raise TypeError("Both arguments must be integers")
return a + b
result = add_numbers(5, 10) # Passing correct types
print(result) # Output: 15
# Passing incorrect types (e.g., add_numbers(5, "10")) will raise a clear error message:
# Output: TypeError: Both arguments must be integers
3. Exception Handling Error: Catching the Wrong Exception Type:
Problem: I encountered an issue where I tried to catch the wrong exception type, which caused the program to crash instead of handling the error properly.
A division by zero raises a
ZeroDivisionError
, but I mistakenly tried to catch aValueError
.Since the
ValueError
exception doesn't match the actual error (ZeroDivisionError
), the program gets crashed.
try:
result = 10 / 0 # This will raise a ZeroDivisionError
except ValueError: # Incorrect exception type
print("You cannot divide by zero!")
Output:
Traceback (most recent call last):
File "<string>", line 2, in <module>
ZeroDivisionError: division by zero
Solution: To fix this error it is important to write the correct exception type as in the above case it is (ZeroDivisionError
) in the except
block.
try:
result = 10 / 0 # This will raise a ZeroDivisionError
except ZeroDivisionError: # Correct exception type
print("You cannot divide by zero!")
# Output: You cannot divide by zero!
4. Enumerate( ) Function Error: Forgetting to Unpack Tuple Values:
Problem: While using the enumerate()
function, It is a common mistake to forget to write index for the first element, which leads to the generation of tuple values as the output.
fruits = ["apple", "banana", "cherry"]
# Forgetting to unpack the tuple returned by enumerate()
for fruit in enumerate(fruits):
print(fruit)
# Output:
(0, 'apple')
(1, 'banana')
(2, 'cherry')
Solution: To fix this, I unpacked the tuple into two variables: one for the index and the other for the value.
fruits = ["apple", "banana", "cherry"]
# Unpacking the tuple returned by enumerate()
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# Output:
0: apple
1: banana
2: cherry
5. Walrus Operator Error: Misunderstanding Scope:
Problem: While using the Walrus operator (:=
), I encountered an issue where the variable declared inside an if
statement unexpectedly overwrote a variable with the same name in the outer (global) scope.
x = 10 # Global variable
if (x := 5) > 3: # Assigns 5 to `x` using the Walrus operator
print(x) # Output: 5
print(x) # Output: 5 (Global `x` is overwritten)
Solution: To avoid this issue, we can use different variable names when working with the Walrus operator, especially if a variable already exists in the global or outer scope as shown below:
x = 10 # Global variable
if (y := 5) > 3: # Use a different variable name
print(y) # Output: 5
print(x) # Output: 10 (Global `x` is not overwritten)
6. Importance of try-except-finally
block inside User-Defined Functions while Handling Errors.
Problem: I found that the exact use of finally
clause is inside a user-defined function for example: without the finally
clause in a try-except
block, essential steps like displaying a confirmation message or running critical tasks such as cleanup or logging may be skipped if the function exits early with a return
keyword especially inside user-defined functions.
# Code Example (Without finally):
def main():
try:
a = int(input("Enter a number: "))
print(a)
return # Function returns here
except Exception as e:
print(e)
return # Function also returns here
print("Goodbye!") # This statement will never be executed due to the `return` above
main()
Solution: To solve the above error we must use the finally
clause which ensures that the code runs regardless of whether the function exits due to a return
statement or an exception.
# Code Example (With finally):
def main():
try:
a = int(input("Enter a number: "))
print(a)
return # Function returns here, but `finally` still executes
except Exception as e:
print(e)
return # Even if this executes, `finally` will still run
finally:
print("Goodbye!") # This will always execute, regardless of `return`
main()
These are the resources that helped me learn:
My GitHub Repository - Link