C# Developer's Guide to Python
Helpful guide to transition to python
A quick reference guide for C# developers learning Python, focusing on common patterns and key differences.
Project Setup & Dependencies
C# Way
Python Way
Classes and Objects
C# Way
Python Way
APIs and Web Applications
C# (ASP.NET Core) Way
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<User> GetUser(int id)
{
var user = _service.GetUser(id);
if (user == null)
return NotFound();
return user;
}
[HttpPost]
public ActionResult<User> CreateUser(UserDto dto)
{
var user = _service.CreateUser(dto);
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
}
}Python (FastAPI) Way
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class UserDto(BaseModel):
name: str
class User(UserDto):
id: int
@app.get("/users/{id}")
async def get_user(id: int):
user = service.get_user(id)
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.post("/users/", response_model=User)
async def create_user(user: UserDto):
return service.create_user(user)Async/Await
C# Way
public async Task<User> GetUserAsync(int id)
{
using var httpClient = new HttpClient();
var response = await httpClient.GetAsync($"api/users/{id}");
return await response.Content.ReadFromJsonAsync<User>();
}Python Way
async def get_user(id: int):
async with httpx.AsyncClient() as client:
response = await client.get(f"api/users/{id}")
return User(**response.json())Data Models and Validation
C# Way
public class UserDto
{
[Required]
[StringLength(100)]
public string Name { get; set; }
[EmailAddress]
public string Email { get; set; }
[Range(0, 150)]
public int Age { get; set; }
}Python Way (with Pydantic)
from pydantic import BaseModel, Field, EmailStr
class UserDto(BaseModel):
name: str = Field(..., max_length=100)
email: EmailStr
age: int = Field(..., ge=0, le=150)Database Access
C# (Entity Framework) Way
public class UserContext : DbContext
{
public DbSet<User> Users { get; set; }
}
// Query
var user = await context.Users
.FirstOrDefaultAsync(u => u.Id == id);Python (SQLAlchemy) Way
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
# Query
user = db.query(User).filter(User.id == id).first()Key Differences to Remember
1. Indentation
C#: Uses curly braces {}
Python: Uses indentation (typically 4 spaces)
2. Naming Conventions
C#: PascalCase for types and methods, camelCase for variables
Python: snake_case for most things, PascalCase for classes
3. Type System
C#: Static typing, compile-time type checking
Python: Dynamic typing with optional type hints
4. Package Management
C#: NuGet packages, centralized .csproj
Python: pip packages, virtual environments
5. Project Structure
C#: Solution/Project structure enforced by framework
Python: More flexible, convention-based structure
Common Gotchas for C# Developers
1. Virtual Environments
Always create and activate a virtual environment
Like having separate .NET versions per project
2. Self Parameter
Python methods need explicit `self` parameter
Similar to `this` in C# but must be declared
3. Package Scoping
Python packages installed globally unless using virtual environment
Different from NuGet's project-scoped packages
4. Async Event Loop
Python's async is different from C#'s
Uses a single event loop, more like JavaScript
5. Type Hints
Optional in Python, required in C#
Used for documentation and IDE support, not runtime enforcement
Best Practices When Transitioning
Use type hints initially - helps catch errors early
Keep virtual environment activated while working
Use modern Python features (dataclasses, f-strings)
Start with FastAPI - similar patterns to ASP.NET
Use an IDE with good Python support (PyCharm, VS Code)





