Writing Code the Python Way
What is "Pythonic" Code?
You can solve any problem in many ways. But Python has a preferred style — clean, readable, and elegant. Code written this way is called Pythonic.
Two programmers can solve the same problem:
# Non-Pythonic — works but ugly numbers = [1, 2, 3, 4, 5] squares = [] for i in range(len(numbers)): squares.append(numbers[i] ** 2)
# Pythonic — clean and elegant squares = [n ** 2 for n in numbers]
Same result. But the second version is shorter, more readable, and more Python-like.
This stage teaches you to write code like an experienced Python developer.
Part 1 — List Comprehensions
The Problem
This pattern appears everywhere:
# Create a new list by transforming another list result = [] for item in original_list: result.append(transform(item))
It works but it's 3 lines every time. List comprehension does it in 1.
Basic List Comprehension
# Syntax new_list = [expression for item in iterable]
Examples:
# Squares of numbersnumbers = [1, 2, 3, 4, 5]# Old waysquares = []for n in numbers:squares.append(n ** 2)# List comprehensionsquares = [n ** 2 for n in numbers]print(squares) # [1, 4, 9, 16, 25]# Uppercase all stringsfruits = ["apple", "banana", "mango"]upper_fruits = [f.upper() for f in fruits]print(upper_fruits) # ['APPLE', 'BANANA', 'MANGO']# Get lengths of wordswords = ["Python", "is", "awesome"]lengths = [len(w) for w in words]print(lengths) # [6, 2, 7]
List Comprehension with Condition
# Syntaxnew_list = [expression for item in iterable if condition]numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]# Only even numbersevens = [n for n in numbers if n % 2 == 0]print(evens) # [2, 4, 6, 8, 10]# Only numbers greater than 5big = [n for n in numbers if n > 5]print(big) # [6, 7, 8, 9, 10]# Squares of only even numberseven_squares = [n ** 2 for n in numbers if n % 2 == 0]print(even_squares) # [4, 16, 36, 64, 100]
Dictionary Comprehension
Same concept for dictionaries:
# Syntaxnew_dict = {key: value for item in iterable}# Square of each number as dictnumbers = [1, 2, 3, 4, 5]squares_dict = {n: n ** 2 for n in numbers}print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}# Flip keys and valuesoriginal = {"name": "Gagan", "age": 22, "city": "Delhi"}flipped = {value: key for key, value in original.items()}print(flipped) # {'Gagan': 'name', 22: 'age', 'Delhi': 'city'}# Filter a dictionarymarks = {"Rahul": 85, "Priya": 92, "Gagan": 45, "Amit": 78, "Neha": 38}passed = {name: mark for name, mark in marks.items() if mark >= 50}print(passed) # {'Rahul': 85, 'Priya': 92, 'Amit': 78}
Set Comprehension
numbers = [1, 2, 2, 3, 3, 3, 4] unique_squares = {n ** 2 for n in numbers} print(unique_squares) # {1, 4, 9, 16} — unique values only
When NOT to Use Comprehensions
Comprehensions are great but don't overuse them:
# Too complex — hard to read result = [x ** 2 for x in range(20) if x % 2 == 0 if x % 3 == 0]
# Better as a regular loop with clear logic result = [] for x in range(20): if x % 2 == 0 and x % 3 == 0: result.append(x ** 2)
Rule — if comprehension is hard to read in one glance, use a regular loop.
Part 2 — Lambda Functions
What is a Lambda?
A lambda is a small anonymous function — a function without a name, written in one line.
# Regular function def square(n): return n ** 2
# Lambda equivalent square = lambda n: n ** 2
print(square(5)) # 25
Syntax:
lambda parameters: expression
Why Lambda?
Lambdas are not meant to replace regular functions. They're useful when you need a small throwaway function in one place — especially with sorted(), map(), filter().
Lambda with sorted()
students = [ {"name": "Rahul", "marks": 85}, {"name": "Priya", "marks": 92}, {"name": "Gagan", "marks": 78}, {"name": "Amit", "marks": 95} ]
# Sort by marks sorted_students = sorted(students, key=lambda s: s["marks"]) for s in sorted_students: print(f"{s['name']}: {s['marks']}")
Output:
Gagan: 78
Rahul: 85
Priya: 92
Amit: 95
# Sort by name sorted_by_name = sorted(students, key=lambda s: s["name"])
# Sort by marks descending sorted_desc = sorted(students, key=lambda s: s["marks"], reverse=True)
map() — Apply Function to Every Item
numbers = [1, 2, 3, 4, 5]# Apply function to each itemsquares = list(map(lambda n: n ** 2, numbers))print(squares) # [1, 4, 9, 16, 25]# Same as list comprehensionsquares = [n ** 2 for n in numbers]# Convert all strings to uppercasenames = ["rahul", "priya", "gagan"]upper = list(map(lambda n: n.upper(), names))print(upper) # ['RAHUL', 'PRIYA', 'GAGAN']
filter() — Filter Items by Condition
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Keep only even numbers evens = list(filter(lambda n: n % 2 == 0, numbers)) print(evens) # [2, 4, 6, 8, 10]
# Keep only passing marks marks = [85, 42, 90, 38, 75, 55, 29] passed = list(filter(lambda m: m >= 50, marks)) print(passed) # [85, 90, 75, 55]
Part 3 — Useful Pythonic Patterns
Unpacking
# Basic unpacking a, b, c = [1, 2, 3] print(a, b, c) # 1 2 3
# Swap variables — Pythonic way x, y = 10, 20 x, y = y, x # swap in one line print(x, y) # 20 10
# Extended unpacking first, *rest = [1, 2, 3, 4, 5] print(first) # 1 print(rest) # [2, 3, 4, 5]
*beginning, last = [1, 2, 3, 4, 5] print(beginning) # [1, 2, 3, 4] print(last) # 5
Enumerate — Already Seen, Important Enough to Revisit
fruits = ["apple", "banana", "mango"]
# Non-Pythonic for i in range(len(fruits)): print(f"{i + 1}. {fruits[i]}")
# Pythonic for i, fruit in enumerate(fruits, start=1): print(f"{i}. {fruit}")
zip — Combine Two Lists
names = ["Rahul", "Priya", "Gagan"] marks = [85, 92, 78]
for name, mark in zip(names, marks): print(f"{name}: {mark}")
Output:
Rahul: 85
Priya: 92
Gagan: 78
# Create dictionary from two lists students_dict = dict(zip(names, marks)) print(students_dict) # {'Rahul': 85, 'Priya': 92, 'Gagan': 78}
any() and all()
marks = [85, 92, 78, 45, 90]
# all() — True if ALL items satisfy condition all_passed = all(m >= 50 for m in marks) print(all_passed) # False — 45 fails
# any() — True if AT LEAST ONE item satisfies condition anyone_failed = any(m < 50 for m in marks) print(anyone_failed) # True — 45 fails
# Practical example passwords = ["abc", "password123", "xyz"] has_strong = any(len(p) >= 8 for p in passwords) print(has_strong) # True — password123 is long enough
Ternary Operator — One Line If/Else
# Regular if/elseage = 20if age >= 18:status = "Adult"else:status = "Minor"# Ternary — one linestatus = "Adult" if age >= 18 else "Minor"print(status) # Adult# In f-stringsage = 20print(f"You are {'Adult' if age >= 18 else 'Minor'}")
_ as Throwaway Variable
When you don't need a variable:
# You need the index but not the value for _ in range(5): print("Hello") # print 5 times, don't need loop variable
# Unpacking but only want some values name, _, city = ("Gagan", 22, "Delhi") # ignore age print(name, city) # Gagan Delhi
Part 4 — Code Quality
Meaningful Names
# Bad names x = 86400 def calc(a, b): return a * b / 100
# Good names SECONDS_IN_DAY = 86400 def calculate_percentage(score, total): return score * total / 100
Constants in UPPER_CASE
# Constants — values that never change MAX_RETRIES = 3 DEFAULT_TIMEOUT = 30 DATABASE_URL = "postgresql://localhost/mydb" PI = 3.14159
Functions Should Do One Thing
# Bad — function doing too much def process_student(name, marks): average = sum(marks) / len(marks) if average >= 90: grade = "A" elif average >= 80: grade = "B" else: grade = "C" print(f"Name: {name}") print(f"Average: {average}") print(f"Grade: {grade}") with open("results.txt", "a") as f: f.write(f"{name},{average},{grade}\n")
# Good — each function does one thing def calculate_average(marks): return sum(marks) / len(marks)
def get_grade(average): if average >= 90: return "A" elif average >= 80: return "B" else: return "C"
def print_result(name, average, grade): print(f"Name: {name}, Average: {average}, Grade: {grade}")
def save_result(name, average, grade): with open("results.txt", "a") as f: f.write(f"{name},{average},{grade}\n")
Docstrings — Document Your Code
def calculate_average(marks): """ Calculate the average of a list of marks.
Args: marks (list): List of numerical marks
Returns: float: The average mark
Example: >>> calculate_average([85, 90, 78]) 84.33 """ if not marks: return 0 return sum(marks) / len(marks)
Docstrings appear when someone calls help(calculate_average). Professional code always has docstrings.
PEP 8 — Python Style Guide
PEP 8 is the official Python style guide. Key rules:
# Indentation — 4 spaces (not tabs) def my_function(): x = 10 return x
# Spaces around operators x = 5 + 3 # correct x=5+3 # wrong
# No space before colon in dict/slice d = {"key": "value"} # correct d = {"key" : "value"} # wrong
# Two blank lines between top-level functions/classes def function_one(): pass
def function_two(): pass
class MyClass: pass
# One blank line between methods inside class class MyClass: def method_one(self): pass
def method_two(self): pass
# Max line length — 79 characters # Long lines — use backslash or parentheses result = (value_one + value_two + value_three + value_four)
# Imports — one per line, at the top import os import json from datetime import datetime
Final Real World Example — Everything Together
A clean, Pythonic, well-structured program:
""" expense_tracker.py A simple expense tracker using Pythonic best practices. """
import json import os from datetime import datetime
EXPENSES_FILE = "expenses.json" CATEGORIES = ["food", "transport", "shopping", "bills", "entertainment", "other"]
def load_expenses(): """Load expenses from JSON file.""" if not os.path.exists(EXPENSES_FILE): return [] with open(EXPENSES_FILE, "r") as file: return json.load(file)
def save_expenses(expenses): """Save expenses to JSON file.""" with open(EXPENSES_FILE, "w") as file: json.dump(expenses, file, indent=4)
def add_expense(expenses): """Add a new expense entry.""" print("\nCategories:", ", ".join(CATEGORIES)) description = input("Description: ").strip() category = input("Category: ").strip().lower() if category not in CATEGORIES: print(f"Invalid category. Using 'other'") category = "other"
try: amount = float(input("Amount (Rs.): ")) if amount <= 0: print("Amount must be positive") return except ValueError: print("Invalid amount") return
expense = { "id": len(expenses) + 1, "description": description, "category": category, "amount": amount, "date": datetime.now().strftime("%Y-%m-%d") }
expenses.append(expense) save_expenses(expenses) print(f"Expense added: Rs.{amount:.2f} for {description}")
def view_expenses(expenses): """Display all expenses.""" if not expenses: print("No expenses recorded yet") return
print(f"\n{'ID':<5} {'Date':<12} {'Category':<15} {'Amount':<12} {'Description'}") print("-" * 60)
for e in expenses: print(f"{e['id']:<5} {e['date']:<12} {e['category']:<15} Rs.{e['amount']:<10.2f} {e['description']}")
total = sum(e["amount"] for e in expenses) print("-" * 60) print(f"{'Total:':<33} Rs.{total:.2f}")
def view_by_category(expenses): """Show expense summary by category.""" if not expenses: print("No expenses recorded yet") return
category_totals = {} for e in expenses: cat = e["category"] category_totals[cat] = category_totals.get(cat, 0) + e["amount"]
print("\n=== Expenses by Category ===") sorted_cats = sorted(category_totals.items(), key=lambda x: x[1], reverse=True) for category, total in sorted_cats: print(f" {category:<15}: Rs.{total:.2f}")
def filter_by_category(expenses): """Filter expenses by category.""" category = input("Enter category: ").strip().lower() filtered = [e for e in expenses if e["category"] == category]
if not filtered: print(f"No expenses in category '{category}'") return
print(f"\n=== {category.title()} Expenses ===") for e in filtered: print(f" {e['date']} — Rs.{e['amount']:.2f} — {e['description']}")
total = sum(e["amount"] for e in filtered) print(f" Total: Rs.{total:.2f}")
def main(): """Main program loop.""" expenses = load_expenses() print(f"Loaded {len(expenses)} existing expenses")
menu_options = { "1": ("Add expense", add_expense), "2": ("View all expenses", view_expenses), "3": ("View by category", view_by_category), "4": ("Filter by category", filter_by_category), "5": ("Exit", None) }
while True: print("\n=== Expense Tracker ===") for key, (label, _) in menu_options.items(): print(f"{key}. {label}")
choice = input("Choice: ").strip()
if choice == "5": print("Goodbye!") break elif choice in menu_options: _, func = menu_options[choice] func(expenses) else: print("Invalid choice")
if __name__ == "__main__": main()
Notice what's Pythonic here:
- Docstrings on every function
- List comprehension for filtering
sum()with generator expressionsorted()with lambda- Dictionary for menu options
.get()for safe dictionary accessif __name__ == "__main__"— standard entry point
if __name__ == "__main__" — Explained
def main():
print("Program running")
if __name__ == "__main__":
main()
When Python runs a file directly — __name__ equals "__main__" so main() runs.
When another file imports this file — __name__ equals the filename so main() does NOT run automatically.
This is standard in every professional Python script. Always write it.
Exercise 🏋️ — Final Project
You've completed all 10 stages. Now build a complete CLI application combining everything:
Personal Finance Manager:
=== Personal Finance Manager ===
1. Add income
2. Add expense
3. View transactions
4. View balance
5. Monthly summary
6. Export to file
7. Exit
Requirements:
- OOP —
Transactionclass,Accountclass - File handling — save/load from JSON
- Error handling — all inputs validated
- Modules — datetime, json, os
- Pythonic code — comprehensions, clean functions, docstrings
- Categories for both income and expenses
- Monthly summary showing income vs expense vs savings
This is your capstone project — it combines every single concept from all 10 stages. Take your time, build it properly.
🎉 Congratulations — You've Completed the Roadmap!
Let's look at everything you've learned:
|
Stage |
Topics |
|
Stage 1 |
Setup,
print, variables, data types, math, input |
|
Stage 2 |
If/else, elif, loops, break,
continue |
|
Stage 3 |
Functions,
parameters, return, scope |
|
Stage 4 |
Lists, tuples, dictionaries,
sets |
|
Stage 5 |
String
methods, formatting, f-strings |
|
Stage 6 |
File read/write, CSV, JSON
files |
|
Stage 7 |
Try/except,
error types, raising exceptions |
|
Stage 8 |
Built-in modules, pip,
external libraries |
|
Stage 9 |
Classes,
objects, inheritance, polymorphism |
|
Stage 10 |
Comprehensions, lambda,
Pythonic patterns |
What's Next After Core Python?
Now that you know Core Python — pick a direction:
Web Development:
- Flask or Django framework
- Build websites and APIs
Data Science / AI:
- NumPy, Pandas, Matplotlib
- Machine Learning with scikit-learn
Automation:
- Selenium — automate browsers
- PyAutoGUI — automate desktop
- Schedule — run tasks automatically
Backend Development:
- FastAPI — modern API framework
- PostgreSQL with psycopg2
- REST API development
No comments:
Post a Comment