Site icon Bệ Phóng Việt

Python FastAPI 2: Bài ôn tập Python cơ bản

Advertisements

Chào mừng bạn quay trở lại với khoá học Python FastAPI. Ở Bài 1, chúng ta đã làm quen với FastAPI và dựng được một endpoint đầu tiên. Trước khi bước vào các chủ đề nâng cao như asyncio, decorators hay metaclasses ở Bài 3, chúng ta cần chắc chắn rằng nền tảng Python cơ bản của bạn đã vững.

Bài này là bài ôn tập Python cơ bản. Nếu bạn đã quen thuộc với Python, hãy xem đây là một checklist để đảm bảo không bỏ sót khái niệm quan trọng nào. Nếu bạn đến từ ngôn ngữ khác (PHP, JavaScript, Java…), bài này sẽ giúp bạn nắm nhanh những gì cần thiết để code FastAPI một cách tự tin 😉

1. Môi trường Python và quản lý package

Trước khi viết bất kỳ dòng code nào, hãy đảm bảo bạn có Python 3.8 trở lên. FastAPI yêu cầu Python 3.8+ để tận dụng đầy đủ tính năng type hints và async.

python --version
# Python 3.11.5

Luôn làm việc trong virtual environment để tránh xung đột package giữa các dự án:

# Tạo virtual environment
python -m venv venv

# Kích hoạt trên Linux/macOS
source venv/bin/activate

# Kích hoạt trên Windows
venv\Scripts\activate

# Cài package
pip install fastapi uvicorn

2. Kiểu dữ liệu cơ bản

Python có 4 kiểu dữ liệu cơ bản mà bạn sẽ dùng hàng ngày khi code FastAPI:

# Số nguyên và số thực
age = 30
price = 19.99

# Chuỗi
name = "Nguyễn Văn A"
greeting = f"Xin chào, {name}! Bạn {age} tuổi."

# Boolean
is_active = True
is_deleted = False

# None (tương đương null trong ngôn ngữ khác)
middle_name = None

Đặc biệt chú ý f-string (có từ Python 3.6) — đây là cách format chuỗi hiện đại và nhanh nhất trong Python. Bạn sẽ dùng nó rất nhiều khi tạo log, error message trong FastAPI.

3. Collection: list, tuple, dict, set

Bốn kiểu collection này xuất hiện liên tục khi bạn xây dựng API. Request body thường là dict, response có thể là list các dict, query parameters có thể là set…

# List - có thứ tự, có thể thay đổi
users = ["Alice", "Bob", "Charlie"]
users.append("David")
print(users[0])  # Alice

# Tuple - có thứ tự, không thể thay đổi
coordinates = (10.762, 106.660)  # toạ độ Sài Gòn

# Dict - cặp key-value, cực kỳ quan trọng cho API
user = {
    "id": 1,
    "name": "Joseph",
    "email": "joseph@example.com",
    "is_active": True
}
print(user["name"])  # Joseph
print(user.get("phone", "N/A"))  # N/A (giá trị mặc định)

# Set - tập hợp các phần tử duy nhất
tags = {"python", "fastapi", "api", "python"}
print(tags)  # {'python', 'fastapi', 'api'}

4. List comprehension và Dict comprehension

Đây là cú pháp “Pythonic” giúp code ngắn gọn, dễ đọc hơn vòng lặp truyền thống. Bạn sẽ gặp rất nhiều trong code FastAPI khi xử lý danh sách dữ liệu trả về từ database.

# Cách truyền thống
squares = []
for i in range(10):
    squares.append(i * i)

# Cách Pythonic với list comprehension
squares = [i * i for i in range(10)]

# Kèm điều kiện lọc
even_squares = [i * i for i in range(10) if i % 2 == 0]
# [0, 4, 16, 36, 64]

# Dict comprehension - rất hữu ích khi transform data
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
user_map = {u["id"]: u["name"] for u in users}
# {1: 'Alice', 2: 'Bob'}

5. Function và type hints

FastAPI được xây dựng dựa trên type hints của Python. Đây là tính năng then chốt mà bạn phải nắm vững. Type hints giúp FastAPI tự động validate dữ liệu, tạo tài liệu Swagger và bắt lỗi ngay khi viết code.

# Function không có type hints - KHÔNG nên
def add(a, b):
    return a + b

# Function có type hints - NÊN dùng khi làm việc với FastAPI
def add(a: int, b: int) -> int:
    return a + b

# Tham số mặc định
def greet(name: str, greeting: str = "Xin chào") -> str:
    return f"{greeting}, {name}!"

# *args và **kwargs
def log_event(event: str, *args, **kwargs):
    print(f"Event: {event}")
    print(f"Args: {args}")
    print(f"Kwargs: {kwargs}")

log_event("user_login", "ip=1.2.3.4", user_id=42, role="admin")

Với các kiểu phức tạp hơn, chúng ta dùng module typing:

from typing import List, Dict, Optional, Union

# List các string
def get_user_names() -> List[str]:
    return ["Alice", "Bob", "Charlie"]

# Dict với key là str, value là int
def get_scores() -> Dict[str, int]:
    return {"Alice": 90, "Bob": 85}

# Optional - có thể là str hoặc None
def find_user(user_id: int) -> Optional[str]:
    if user_id == 1:
        return "Alice"
    return None

# Union - có thể là một trong nhiều kiểu
def parse_id(value: Union[int, str]) -> int:
    return int(value)

Từ Python 3.10 trở lên, bạn có thể viết gọn hơn:

# Python 3.10+
def find_user(user_id: int) -> str | None:
    ...

def get_user_names() -> list[str]:
    ...

def parse_id(value: int | str) -> int:
    ...

6. Lớp (Class) và OOP

FastAPI dùng class để định nghĩa Pydantic models (request/response schema), dependency injection và nhiều thứ khác. Bạn cần nắm vững cách khai báo class trong Python.

class User:
    # Constructor
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email
        self.is_active = True

    # Instance method
    def deactivate(self) -> None:
        self.is_active = False

    # String representation
    def __repr__(self) -> str:
        return f"User(name={self.name}, email={self.email})"


# Sử dụng
user = User(name="Joseph", email="joseph@example.com")
print(user)  # User(name=Joseph, email=joseph@example.com)
user.deactivate()
print(user.is_active)  # False

Kế thừa (inheritance) cũng rất quan trọng, đặc biệt khi bạn làm việc với Pydantic BaseModel trong FastAPI:

class Animal:
    def __init__(self, name: str):
        self.name = name

    def speak(self) -> str:
        return "Some sound"


class Dog(Animal):
    def speak(self) -> str:
        return f"{self.name} says: Gâu gâu!"


class Cat(Animal):
    def speak(self) -> str:
        return f"{self.name} says: Meo meo!"


dog = Dog("Milu")
print(dog.speak())  # Milu says: Gâu gâu!

7. Xử lý ngoại lệ (Exception Handling)

Khi xây dựng API, xử lý lỗi là kỹ năng bắt buộc. Bạn cần biết cách try/except để bắt lỗi và trả về response phù hợp cho client.

def divide(a: int, b: int) -> float:
    try:
        result = a / b
    except ZeroDivisionError:
        print("Không thể chia cho 0")
        return 0.0
    except TypeError as e:
        print(f"Lỗi kiểu dữ liệu: {e}")
        return 0.0
    else:
        # Chạy khi không có exception
        return result
    finally:
        # Luôn luôn chạy
        print("Hoàn tất phép chia")


# Tạo exception tuỳ chỉnh
class UserNotFoundError(Exception):
    def __init__(self, user_id: int):
        self.user_id = user_id
        super().__init__(f"Không tìm thấy user với id={user_id}")


def get_user(user_id: int):
    if user_id != 1:
        raise UserNotFoundError(user_id)
    return {"id": 1, "name": "Joseph"}

8. Làm việc với file và JSON

JSON là định dạng dữ liệu chuẩn khi giao tiếp giữa client và API. Python có module json built-in rất tiện dụng.

import json

# Chuyển dict sang JSON string
user = {"id": 1, "name": "Joseph", "roles": ["admin", "user"]}
json_str = json.dumps(user, ensure_ascii=False, indent=2)
print(json_str)

# Parse JSON string sang dict
data = json.loads('{"name": "Alice", "age": 30}')
print(data["name"])  # Alice

# Đọc/ghi file JSON
with open("users.json", "w", encoding="utf-8") as f:
    json.dump(user, f, ensure_ascii=False, indent=2)

with open("users.json", "r", encoding="utf-8") as f:
    loaded_user = json.load(f)

Chú ý dùng with statement (context manager) — đây là cách an toàn để đảm bảo file luôn được đóng đúng cách, kể cả khi có lỗi xảy ra.

9. Module và package

Khi dự án FastAPI lớn lên, bạn sẽ chia code ra nhiều file và thư mục. Hiểu cách import trong Python là điều cần thiết.

my_project/
├── main.py
├── models/
│   ├── __init__.py
│   ├── user.py
│   └── product.py
└── utils/
    ├── __init__.py
    └── helpers.py
# main.py
from models.user import User
from models.product import Product
from utils.helpers import format_date

# Hoặc import relative trong package
# models/user.py
from ..utils.helpers import format_date

Sự tồn tại của file __init__.py báo cho Python biết thư mục đó là một package có thể import được.

10. Lambda, map, filter

Ba công cụ này giúp bạn xử lý dữ liệu theo phong cách functional, rất hữu ích khi transform response data trong FastAPI.

# Lambda - hàm ẩn danh
add = lambda a, b: a + b
print(add(2, 3))  # 5

numbers = [1, 2, 3, 4, 5]

# map - áp dụng hàm lên từng phần tử
squared = list(map(lambda x: x * x, numbers))
# [1, 4, 9, 16, 25]

# filter - lọc phần tử theo điều kiện
even = list(filter(lambda x: x % 2 == 0, numbers))
# [2, 4]

# Tuy nhiên, list comprehension thường "Pythonic" hơn
squared = [x * x for x in numbers]
even = [x for x in numbers if x % 2 == 0]

Bài tập ôn tập

Trước khi chuyển sang Bài 3, hãy thử hoàn thành bài tập nhỏ sau để tự kiểm tra:

Viết một hàm process_users nhận vào một list các dict (mỗi dict có id, name, age) và trả về một dict với key là id, value là chuỗi mô tả user đã được format. Chỉ lấy các user từ 18 tuổi trở lên. Sử dụng type hints đầy đủ.

from typing import List, Dict

def process_users(users: List[Dict]) -> Dict[int, str]:
    return {
        u["id"]: f"{u['name']} ({u['age']} tuổi)"
        for u in users
        if u["age"] >= 18
    }


# Test
data = [
    {"id": 1, "name": "Alice", "age": 25},
    {"id": 2, "name": "Bob", "age": 17},
    {"id": 3, "name": "Charlie", "age": 30},
]

print(process_users(data))
# {1: 'Alice (25 tuổi)', 3: 'Charlie (30 tuổi)'}

Nếu bạn đọc code trên mà hiểu được toàn bộ logic — từ type hints, dict comprehension, điều kiện lọc, đến f-string — thì xin chúc mừng, bạn đã sẵn sàng cho các chủ đề nâng cao!

Trong bài này, chúng ta đã ôn lại những kiến thức Python cơ bản quan trọng nhất để làm việc với FastAPI:

Môi trường và virtual environment, kiểu dữ liệu cơ bản, các collection (list, tuple, dict, set), list/dict comprehension, function với type hints (cực kỳ quan trọng với FastAPI), OOP cơ bản, xử lý ngoại lệ, làm việc với JSON, module/package, và các công cụ functional như lambda/map/filter.

Bài 3 tiếp theo, chúng ta sẽ đi sâu vào các chủ đề Python nâng cao — asyncio (lập trình bất đồng bộ, linh hồn của FastAPI), decorators (thứ tạo nên các cú pháp như @app.get("/")), và metaclasses (cơ chế đứng sau Pydantic BaseModel). Đây là những khái niệm sẽ giúp bạn hiểu FastAPI hoạt động bên trong như thế nào, không chỉ “biết dùng” mà còn “biết tại sao”.

Hẹn gặp lại bạn ở bài tiếp theo! 🚀

Exit mobile version