Introduction
Debugging is an essential skill for writing reliable code, and following best practices ensures clean, efficient, and maintainable Python programs. This step will guide you through debugging techniques and Python coding standards.
1. Debugging Techniques
Using Print Statements
def add_numbers(a, b):
print(f"Adding {a} and {b}")
return a + b
result = add_numbers(5, 3)
print("Result:", result)
Best for: Quick debugging but should not be used in production code.
Using the Python Debugger (pdb
)
import pdb
def divide(a, b):
pdb.set_trace() # Debugger starts here
return a / b
divide(10, 2)
Commands in pdb
:
n
(next line)s
(step into function)c
(continue execution)q
(quit debugger)
Using Logging for Debugging
pip install logging
import logging
logging.basicConfig(level=logging.DEBUG)
def multiply(a, b):
logging.debug(f"Multiplying {a} and {b}")
return a * b
multiply(4, 5)
Best for: Production debugging and logging system events.
2. Handling Errors Gracefully
Using Try-Except Blocks
try:
x = int(input("Enter a number: "))
result = 10 / x
except ValueError:
print("Invalid input. Please enter a number.")
except ZeroDivisionError:
print("Cannot divide by zero.")
else:
print("Result:", result)
finally:
print("Execution completed.")
Best for: Handling known errors and preventing program crashes.
3. Best Practices in Python
1. Follow PEP 8 (Python Style Guide)
- Use 4 spaces per indentation level (avoid tabs).
- Keep lines under 79 characters long.
- Use meaningful variable names.
- Add comments where necessary.
2. Use List Comprehensions for Efficient Code
squares = [x**2 for x in range(10)]
print(squares)
Best for: Writing concise and readable code.
3. Avoid Mutable Default Arguments
def add_item(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
Why? Default arguments are shared between function calls.
4. Use F-Strings for String Formatting (Python 3.6+)
name = "Alice"
age = 25
print(f"My name is {name} and I am {age} years old.")
Best for: Improving readability and performance.
5. Optimize Performance with Generators
def generate_numbers():
for i in range(5):
yield i
for num in generate_numbers():
print(num)
Best for: Efficient memory usage in large datasets.
Exercises
- Debug a function using
pdb
and analyze step-by-step execution. - Implement logging in a script instead of print statements.
- Write a function with
try-except-finally
to handle multiple exceptions. - Refactor a piece of code using list comprehensions.
- Optimize a function using a generator instead of returning a list.
Conclusion
You have now learned debugging techniques, error handling, and Python best practices to write cleaner and more efficient code. The next step is to build a real-world project and contribute to open source.