0% found this document useful (0 votes)
1 views18 pages

Python Foundations Guide

This guide is a fast-track resource for .NET developers transitioning to Python, focusing on key differences and practical applications over a 2-3 week timeline. It covers essential topics such as Python syntax, data types, functions, OOP, error handling, and FastAPI. The guide emphasizes leveraging existing programming knowledge while learning Python's idioms for effective project development and interview preparation.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views18 pages

Python Foundations Guide

This guide is a fast-track resource for .NET developers transitioning to Python, focusing on key differences and practical applications over a 2-3 week timeline. It covers essential topics such as Python syntax, data types, functions, OOP, error handling, and FastAPI. The guide emphasizes leveraging existing programming knowledge while learning Python's idioms for effective project development and interview preparation.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

🐍

PYTHON FOUNDATIONS
A .NET Developer's Fast-Track Guide
Phase 1 of Your Python + LLM Journey
Introduction
Welcome, .NET developer! This guide is designed specifically for you — it skips the absolute basics
and focuses on what's different in Python vs C#, along with everything you need to build real projects
and ace interviews.

⏱ Timeline
Estimated completion: 2–3 weeks (1–2 hours/day). Each section includes exercises. Build a small
project at the end of each week.

What You'll Cover


• Week 1 — Python syntax, data types, functions, and OOP
• Week 2 — File I/O, error handling, modules, virtual environments
• Week 2–3 — FastAPI, async/await, Pydantic, and HTTP clients

💡 Your Advantage
You already understand APIs, backend architecture, async patterns, and OOP. Python will feel
familiar fast. The key is learning Python's idioms — not re-learning programming.
Week 1 — Python Syntax & Core Concepts

1.1 — Setting Up Your Environment


Install Python 3.11+ from [Link]. Then set up your dev environment:

# Check Python version


python --version

# Create a virtual environment (do this for every project)


python -m venv venv

# Activate it (Windows)
venv\Scripts\activate

# Activate it (Mac/Linux)
source venv/bin/activate

# Install packages
pip install requests fastapi uvicorn pydantic

# Save dependencies (like [Link] or .csproj)


pip freeze > [Link]

# Recreate from requirements


pip install -r [Link]

🔧 Recommended IDE
Use VS Code with the Python extension, or PyCharm Community Edition. Both have great .NET
developer integrations.

1.2 — Python vs C# — Key Syntax Differences


Let's get the translation out of the way first. Here's a direct comparison of common patterns:

Concept C# (.NET) Python


Variable declaration string name = "Naman"; name = "Naman"
Type hints (optional) string name = "Naman"; name: str = "Naman"
Null check if (x == null) if x is None:
String interpolation $"Hello {name}" f"Hello {name}"
List List<int> nums = new List<int>() nums: list[int] = []
Dictionary Dictionary<string, int>() d: dict[str, int] = {}
Print [Link](x) print(x)
Concept C# (.NET) Python
Try/Catch try { } catch (Exception e) try: ... except Exception as e:
Async method async Task<T> Method() async def method() -> T:
Lambda x => x * 2 lambda x: x * 2

1.3 — Variables, Types & Type Hints


Python is dynamically typed but supports optional type hints (strongly recommended for LLM work and
interviews):

# Basic types
name: str = "Naman"
age: int = 28
score: float = 9.5
is_active: bool = True
nothing: None = None

# Python has no separate char type — use str


letter: str = "A"

# Type checking at runtime (useful for debugging)


print(type(name)) # <class 'str'>
print(isinstance(age, int)) # True

# f-strings (your new best friend)


greeting = f"Hello, {name}! You are {age} years old."
formatted = f"Score: {score:.2f}" # Score: 9.50

1.4 — Collections: Lists, Dicts, Tuples, Sets


Lists (equivalent to List<T>)
# List creation and operations
fruits: list[str] = ["apple", "banana", "cherry"]

[Link]("mango") # Add to end


[Link](0, "avocado") # Insert at index
[Link]("banana") # Remove by value
popped = [Link]() # Remove and return last item

# Slicing (powerful — no equivalent in C# arrays)


first_two = fruits[0:2] # ['avocado', 'apple']
last_two = fruits[-2:] # last 2 items
reversed_list = fruits[::-1] # reverse

# List comprehension (key Python pattern!)


numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers] # [1, 4, 9, 16, 25]
evens = [n for n in numbers if n % 2 == 0] # [2, 4]
Dictionaries (equivalent to Dictionary<K,V>)
# Dictionary creation
user: dict[str, any] = {
"name": "Naman",
"age": 28,
"role": "Developer"
}

# Safe access (like TryGetValue)


name = [Link]("name", "Unknown") # Default if key missing

# Looping over dict


for key, value in [Link]():
print(f"{key}: {value}")

# Dict comprehension
lengths = {word: len(word) for word in ["hello", "world"]}
# {'hello': 5, 'world': 5}

# Merging dicts (Python 3.9+)


defaults = {"theme": "dark", "lang": "en"}
overrides = {"lang": "hi"}
merged = defaults | overrides # {'theme': 'dark', 'lang': 'hi'}

Tuples & Sets


# Tuples — immutable, ordered (like readonly structs)
point: tuple[int, int] = (10, 20)
x, y = point # unpacking

# Named tuple (more readable)


from typing import NamedTuple
class Point(NamedTuple):
x: int
y: int

p = Point(10, 20)
print(p.x, p.y)

# Sets — unique unordered values


skills = {"python", "csharp", "python"}
print(skills) # {'python', 'csharp'} — duplicates removed

a = {1, 2, 3}
b = {2, 3, 4}
print(a & b) # {2, 3} — intersection
print(a | b) # {1, 2, 3, 4} — union
print(a - b) # {1} — difference
1.5 — Functions
# Basic function with type hints
def greet(name: str, greeting: str = "Hello") -> str:
return f"{greeting}, {name}!"

print(greet("Naman")) # Hello, Naman!


print(greet("Naman", "Hey")) # Hey, Naman!
print(greet(greeting="Hi", name="Naman")) # keyword args

# *args and **kwargs (variable arguments)


def log(*messages: str, level: str = "INFO") -> None:
for msg in messages:
print(f"[{level}] {msg}")

log("Starting", "Processing", "Done", level="DEBUG")

# Lambda (inline functions)


double = lambda x: x * 2
add = lambda x, y: x + y

# Using built-in higher-order functions


nums = [3, 1, 4, 1, 5, 9]
sorted_nums = sorted(nums) # [1, 1, 3, 4, 5, 9]
sorted_desc = sorted(nums, reverse=True) # [9, 5, 4, 3, 1, 1]

people = [{"name": "Bob", "age": 30}, {"name": "Alice", "age": 25}]


by_age = sorted(people, key=lambda p: p["age"]) # sort by age

1.6 — Object-Oriented Programming


Python OOP is similar to C# but with some key differences. The most important: self is explicit (like this
but you write it).

from dataclasses import dataclass


from typing import Optional

# Regular class
class Animal:
# Class variable (shared across instances)
kingdom: str = "Animalia"

def __init__(self, name: str, sound: str):


# Instance variables
[Link] = name
[Link] = sound
self._secret = "hidden" # _ prefix = private by convention

def speak(self) -> str:


return f"{[Link]} says {[Link]}"

# String representation (like ToString())


def __repr__(self) -> str:
return f"Animal(name={[Link]!r})"

# Inheritance
class Dog(Animal):
def __init__(self, name: str, breed: str):
super().__init__(name, "Woof") # super() like base()
[Link] = breed

def fetch(self, item: str) -> str:


return f"{[Link]} fetches the {item}!"

dog = Dog("Rex", "Labrador")


print([Link]()) # Rex says Woof
print([Link]("ball")) # Rex fetches the ball!

Dataclasses (your new favorite — like C# records)


from dataclasses import dataclass, field
from typing import Optional

@dataclass
class User:
name: str
email: str
age: int = 0
tags: list[str] = field(default_factory=list)
is_active: bool = True

def display_name(self) -> str:


return [Link]()

# Auto-generates __init__, __repr__, __eq__


user1 = User(name="naman", email="n@[Link]")
user2 = User(name="naman", email="n@[Link]")
print(user1 == user2) # True — value equality!
print(user1) # User(name='naman', email='n@[Link]', ...)
Week 2 — Python in Practice

2.1 — Error Handling


# Basic try/except (like try/catch)
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Math error: {e}")
except (TypeError, ValueError) as e:
print(f"Type/Value error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
raise # re-raise the exception
else:
print("No error occurred") # runs if no exception
finally:
print("Always runs") # like C# finally

# Custom exceptions
class ValidationError(Exception):
def __init__(self, field: str, message: str):
[Link] = field
super().__init__(f"Validation failed for {field}: {message}")

def validate_age(age: int) -> None:


if age < 0 or age > 150:
raise ValidationError("age", "Must be between 0 and 150")

try:
validate_age(-5)
except ValidationError as e:
print([Link], str(e)) # age Validation failed for age: ...

2.2 — File I/O


# Reading files (context manager = using in C#)
with open("[Link]", "r", encoding="utf-8") as f:
content = [Link]() # entire file as string
# OR
lines = [Link]() # list of lines
# OR
for line in f: # memory efficient for large files
print([Link]())

# Writing files
with open("[Link]", "w", encoding="utf-8") as f:
[Link]("Hello World\n")
[Link](["Line 1\n", "Line 2\n"])

# Appending
with open("[Link]", "a") as f:
[Link]("New log entry\n")

# JSON files (very common in LLM work)


import json

# Write JSON
data = {"name": "Naman", "scores": [90, 85, 92]}
with open("[Link]", "w") as f:
[Link](data, f, indent=2)

# Read JSON
with open("[Link]", "r") as f:
loaded = [Link](f)

# Path operations (use pathlib — not [Link])


from pathlib import Path

base = Path("./data")
file_path = base / "results" / "[Link]" # path joining
file_path.[Link](parents=True, exist_ok=True) # create dirs
exists = file_path.exists()

2.3 — Decorators
Decorators are a key Python pattern — you'll see them everywhere in FastAPI and LLM frameworks.
They're similar to C# attributes but they actually execute code.

import time
from functools import wraps

# A decorator is just a function that wraps another function


def timer(func):
@wraps(func) # preserves function metadata
def wrapper(*args, **kwargs):
start = [Link]()
result = func(*args, **kwargs)
end = [Link]()
print(f"{func.__name__} took {end - start:.3f}s")
return result
return wrapper

@timer # same as: process_data = timer(process_data)


def process_data(n: int) -> list[int]:
return [i ** 2 for i in range(n)]

result = process_data(10000) # process_data took 0.002s

# Decorator with parameters


def retry(max_attempts: int = 3):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
print(f"Attempt {attempt + 1} failed: {e}")
return wrapper
return decorator

@retry(max_attempts=3)
def call_api(url: str) -> dict:
import requests
return [Link](url).json()

2.4 — Async / Await in Python


Good news: async/await in Python works almost identically to C#. The main difference is you need
asyncio to run it.

import asyncio
import httpx # async HTTP client (pip install httpx)

# Async function
async def fetch_data(url: str) -> dict:
async with [Link]() as client:
response = await [Link](url)
response.raise_for_status()
return [Link]()

# Running multiple async tasks concurrently


async def fetch_multiple(urls: list[str]) -> list[dict]:
tasks = [fetch_data(url) for url in urls]
results = await [Link](*tasks) # like [Link]()
return results

# Entry point
async def main():
urls = [
"[Link]
"[Link]
]
results = await fetch_multiple(urls)
for r in results:
print(r["login"], r["public_repos"])

# Run the event loop


if __name__ == "__main__":
[Link](main())

2.5 — Comprehensions & Generators


These are distinctly Pythonic — interviewers love asking about these.
# List comprehension (already covered)
squares = [x**2 for x in range(10)]

# Dict comprehension
word_lengths = {word: len(word) for word in ["hello", "world", "python"]}

# Set comprehension
unique_lengths = {len(word) for word in ["hi", "hello", "hey"]}

# Nested comprehension
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Generator (memory-efficient, lazy evaluation)


# Use () instead of [] — doesn't load all into memory
big_squares = (x**2 for x in range(1_000_000)) # only computes on demand

# Generator function (like IEnumerable<T> yield return)


def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b

fib = fibonacci()
first_10 = [next(fib) for _ in range(10)]
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Week 2–3 — FastAPI & Real-World Python

3.1 — FastAPI Basics


FastAPI is your entry point to Python backend work. If you know [Link] Core, you'll feel right at
home — it uses decorators instead of attributes, and Pydantic instead of data annotations.

# pip install fastapi uvicorn pydantic

from fastapi import FastAPI, HTTPException, Depends


from pydantic import BaseModel, EmailStr, validator
from typing import Optional

app = FastAPI(title="My API", version="1.0")

# Pydantic model (like C# DTO with data annotations)


class UserCreate(BaseModel):
name: str
email: str
age: int

@validator("age")
def age_must_be_positive(cls, v):
if v < 0:
raise ValueError("Age must be positive")
return v

class UserResponse(BaseModel):
id: int
name: str
email: str

# GET endpoint
@[Link]("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
# Simulated DB lookup
if user_id != 1:
raise HTTPException(status_code=404, detail="User not found")
return {"id": 1, "name": "Naman", "email": "n@[Link]"}

# POST endpoint
@[Link]("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
# user is auto-validated and parsed
return {"id": 100, "name": [Link], "email": [Link]}

# Run: uvicorn main:app --reload


# Swagger UI auto-generated at: [Link]
3.2 — Pydantic (Deep Dive)
Pydantic is everywhere in the LLM ecosystem. Master this — it's used by LangChain, FastAPI,
OpenAI's SDK, and more.

from pydantic import BaseModel, Field, validator, model_validator


from typing import Optional, Literal
from datetime import datetime

class Address(BaseModel):
street: str
city: str
country: str = "India"

class Profile(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: str = Field(..., pattern=r"^[\w.-]+@[\w.-]+\.\w+$")
age: int = Field(..., ge=0, le=150)
role: Literal["admin", "user", "guest"] = "user"
address: Optional[Address] = None
created_at: datetime = Field(default_factory=[Link])

@validator("name")
def name_must_be_capitalized(cls, v):
return [Link]()

# Usage
p = Profile(name="naman mittal", email="n@[Link]", age=28)
print([Link]) # Naman Mittal (auto-capitalized)
print(p.model_dump()) # dict representation
print(p.model_dump_json()) # JSON string

# Parsing from dict (common when receiving API responses)


data = {"name": "test user", "email": "t@[Link]", "age": 25}
profile = Profile.model_validate(data)

3.3 — Making HTTP Requests


import httpx
import asyncio

# Sync requests (simple scripts)


import requests

response = [Link](
"[Link]
headers={"Authorization": "Bearer your-api-key"},
timeout=30
)
response.raise_for_status() # raises exception if 4xx/5xx
data = [Link]()

# POST with JSON body


response = [Link](
"[Link]
json={"key": "value"}, # auto sets Content-Type: application/json
headers={"Authorization": "Bearer token"}
)

# Async HTTP (use in FastAPI / LLM apps)


async def call_llm_api(prompt: str) -> str:
async with [Link](timeout=60) as client:
response = await [Link](
"[Link]
headers={
"x-api-key": "your-key",
"anthropic-version": "2023-06-01",
"content-type": "application/json"
},
json={
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 1024,
"messages": [{"role": "user", "content": prompt}]
}
)
result = [Link]()
return result["content"][0]["text"]
Key Python Patterns for Interviews

4.1 — The Walrus Operator & Modern Python


# Walrus operator := (Python 3.8+) — assign and use in expression
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Instead of:
n = len(data)
if n > 5:
print(f"Long list: {n}")

# You can write:


if (n := len(data)) > 5:
print(f"Long list: {n}")

# Useful in while loops


import re
text = "The price is 42 dollars"
if match := [Link](r"\d+", text):
print(f"Found number: {[Link]()}") # Found number: 42

4.2 — Context Managers (with statement)


# Built-in: files, locks, DB connections
with open("[Link]") as f:
data = [Link]() # file auto-closes after block

# Custom context manager using class


class Timer:
def __enter__(self):
import time
[Link] = [Link]()
return self

def __exit__(self, *args):


import time
[Link] = [Link]() - [Link]
print(f"Elapsed: {[Link]:.3f}s")

with Timer() as t:
result = sum(range(1_000_000))
# Elapsed: 0.032s

# Using contextlib (easier)


from contextlib import contextmanager

@contextmanager
def managed_resource(name: str):
print(f"Acquiring {name}")
try:
yield name
finally:
print(f"Releasing {name}")

with managed_resource("DB connection") as conn:


print(f"Using {conn}")

4.3 — String Operations (Interview Favorites)


# Common string methods
text = " Hello, World! "
print([Link]()) # 'Hello, World!'
print([Link]()) # ' hello, world! '
print([Link]("World", "Python")) # ' Hello, Python! '
print([Link](",")) # [' Hello', ' World! ']

# Join (opposite of split)


words = ["Python", "is", "awesome"]
sentence = " ".join(words) # 'Python is awesome'
csv_line = ",".join(words) # 'Python,is,awesome'

# Check contents
print("hello".startswith("he")) # True
print("hello123".isalnum()) # True
print(" ".isspace()) # True

# f-string formatting
pi = 3.14159
print(f"{pi:.2f}") # 3.14
print(f"{pi:10.2f}") # ' 3.14' (right aligned, width 10)
print(f"{1000000:,}") # 1,000,000

# Regular expressions
import re
email = "user@[Link]"
is_valid = bool([Link](r"^[\w.-]+@[\w.-]+\.\w+$", email))
all_numbers = [Link](r"\d+", "I have 3 cats and 2 dogs")
# ['3', '2']
Your 3-Week Study Plan
Week Topics Daily Goal Project
Week 1 Days 1-7 Syntax, Types, 1 section/day + 5 CLI tool: JSON data
Collections, Functions, exercises processor
OOP, Dataclasses
Week 2 Days 8-14 Error Handling, File 1 section/day + build Async web scraper or
I/O, Decorators, something API client
Async/Await,
Comprehensions
Week 2-3 Days 12-21 FastAPI, Pydantic, Build and break things Full FastAPI CRUD
httpx, Virtual Envs, REST API
Project structure

Daily Exercise Template


For each section, do this:
1. Read the section and run all code examples yourself
2. Modify the examples — break them intentionally, then fix them
3. Write 1 small function/class using the concept from scratch
4. Compare: how would I have done this in C#?

Recommended Tools & Resources


Resource Use For Link
Official Python Docs Reference, stdlib modules [Link]
Real Python Tutorials with .NET comparison [Link]
FastAPI Docs Best API framework docs ever [Link]
Pydantic Docs Essential for LLM work [Link]
Python Exercises Interview prep exercises [Link]/tracks/python

🎯 Interview Tip
Interviewers love asking about: list comprehensions vs loops (performance), generators vs lists
(memory), async vs threading, and dataclasses vs Pydantic. Be ready to explain trade-offs, not just
syntax.

✅ Done with Phase 1?


Move to Phase 2: LLM Basics — OpenAI/Anthropic APIs, prompt engineering, function calling, and
your first RAG pipeline. Your FastAPI knowledge will be essential there.
Python Foundations Guide · Prepared for Naman · Masters' Union AI Lab

You might also like