Python Giai Đoạn 2: OOP & Tính Năng Nâng Cao

Python Giai Đoạn 2: OOP & Tính Năng Nâng Cao
Chào mừng bạn đến với Giai Đoạn 2 của Lộ Trình Học Python! Trong giai đoạn này, bạn sẽ thành thạo lập trình hướng đối tượng (OOP) và các tính năng nâng cao đặc trưng của Python giúp bạn viết code sạch, dễ bảo trì và chuyên nghiệp.
Những Gì Bạn Sẽ Học
✅ Classes và objects trong Python
✅ Kế thừa và ghi đè phương thức
✅ Property decorators và phương thức đặc biệt
✅ Dataclasses (Python 3.10+)
✅ List/dict/set comprehensions
✅ Generator expressions
✅ Decorators cơ bản
✅ Context managers
✅ Type hints nền tảng
Điều Kiện Tiên Quyết
Trước khi bắt đầu giai đoạn này, bạn nên thành thạo:
- Cú pháp Python và các kiểu dữ liệu cơ bản (Giai Đoạn 1)
- Functions và control flow
- Lists, dictionaries, và cấu trúc dữ liệu cơ bản
- File I/O và xử lý ngoại lệ
1. Classes và Objects
Classes là bản thiết kế để tạo objects. Chúng đóng gói dữ liệu (thuộc tính) và hành vi (phương thức) lại với nhau.
Cú Pháp Class Cơ Bản
class User:
"""Đại diện cho người dùng trong hệ thống."""
def __init__(self, username: str, email: str) -> None:
"""Khởi tạo người dùng mới."""
self.username = username
self.email = email
self.is_active = True # Giá trị mặc định
def deactivate(self) -> None:
"""Vô hiệu hóa tài khoản người dùng."""
self.is_active = False
def __str__(self) -> str:
"""Biểu diễn chuỗi cho người dùng."""
status = "active" if self.is_active else "inactive"
return f"User({self.username}, {status})"
# Tạo instances
user1 = User("alice", "[email protected]")
user2 = User("bob", "[email protected]")
print(user1) # User(alice, active)
user1.deactivate()
print(user1) # User(alice, inactive)Phương Thức Đặc Biệt (Magic Methods)
Python cung cấp các phương thức đặc biệt cho phép bạn tùy chỉnh hành vi của object:
class BankAccount:
"""Đại diện cho tài khoản ngân hàng."""
def __init__(self, account_number: str, balance: float = 0.0) -> None:
self.account_number = account_number
self.balance = balance
def __str__(self) -> str:
"""Biểu diễn chuỗi thân thiện với người dùng."""
return f"Account {self.account_number}: ${self.balance:.2f}"
def __repr__(self) -> str:
"""Biểu diễn cho developer (dùng cho debug)."""
return f"BankAccount('{self.account_number}', {self.balance})"
def __eq__(self, other: object) -> bool:
"""Kiểm tra bằng nhau dựa trên số tài khoản."""
if not isinstance(other, BankAccount):
return NotImplemented
return self.account_number == other.account_number
def __add__(self, amount: float) -> "BankAccount":
"""Cho phép thêm tiền bằng toán tử +."""
self.balance += amount
return self
# Sử dụng
account = BankAccount("12345", 1000.0)
print(str(account)) # Account 12345: $1000.00
print(repr(account)) # BankAccount('12345', 1000.0)
account + 500 # Thêm tiền bằng +
print(account) # Account 12345: $1500.00Các phương thức đặc biệt phổ biến:
__init__: Constructor__str__: Chuỗi thân thiện (dùng bởiprint())__repr__: Biểu diễn cho developer (dùng trong REPL)__eq__,__lt__,__gt__: Toán tử so sánh__len__: Độ dài (cholen())__getitem__,__setitem__: Truy cập chỉ mục
2. Kế Thừa và Đa Hình
Kế thừa cho phép các class kế thừa thuộc tính và phương thức từ class cha.
Kế Thừa Cơ Bản
from typing import Optional
class Animal:
"""Class cơ sở cho tất cả động vật."""
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def speak(self) -> str:
"""Phát ra âm thanh (sẽ được ghi đè)."""
raise NotImplementedError("Subclasses phải implement speak()")
def info(self) -> str:
"""Lấy thông tin động vật."""
return f"{self.name} {self.age} tuổi"
class Dog(Animal):
"""Chó là một loại động vật."""
def __init__(self, name: str, age: int, breed: str) -> None:
super().__init__(name, age) # Gọi constructor cha
self.breed = breed
def speak(self) -> str:
"""Chó sủa."""
return "Gâu gâu!"
def fetch(self, item: str) -> str:
"""Hành vi đặc trưng của chó."""
return f"{self.name} nhặt {item}"
class Cat(Animal):
"""Mèo là một loại động vật."""
def __init__(self, name: str, age: int, indoor: bool = True) -> None:
super().__init__(name, age)
self.indoor = indoor
def speak(self) -> str:
"""Mèo kêu."""
return "Meo meo!"
# Đa hình: các kiểu khác nhau, giao diện giống nhau
animals: list[Animal] = [
Dog("Buddy", 5, "Golden Retriever"),
Cat("Whiskers", 3),
Dog("Max", 2, "Beagle"),
]
for animal in animals:
print(f"{animal.name} kêu: {animal.speak()}")
# Buddy kêu: Gâu gâu!
# Whiskers kêu: Meo meo!
# Max kêu: Gâu gâu!Đa Kế Thừa và Method Resolution Order (MRO)
class Flyable:
"""Mixin cho khả năng bay."""
def fly(self) -> str:
return "Tôi có thể bay!"
class Swimmable:
"""Mixin cho khả năng bơi."""
def swim(self) -> str:
return "Tôi có thể bơi!"
class Duck(Animal, Flyable, Swimmable):
"""Vịt có thể bay và bơi."""
def speak(self) -> str:
return "Quạc quạc!"
duck = Duck("Donald", 2)
print(duck.speak()) # Quạc quạc!
print(duck.fly()) # Tôi có thể bay!
print(duck.swim()) # Tôi có thể bơi!
# Kiểm tra Method Resolution Order
print(Duck.__mro__)
# (<class 'Duck'>, <class 'Animal'>, <class 'Flyable'>,
# <class 'Swimmable'>, <class 'object'>)3. Properties và Descriptors
Properties cung cấp cách tùy chỉnh truy cập thuộc tính trong khi duy trì giao diện sạch.
Sử Dụng @property Decorator
class Temperature:
"""Nhiệt độ với Celsius và Fahrenheit."""
def __init__(self, celsius: float) -> None:
self._celsius = celsius # Thuộc tính private
@property
def celsius(self) -> float:
"""Lấy nhiệt độ theo Celsius."""
return self._celsius
@celsius.setter
def celsius(self, value: float) -> None:
"""Đặt nhiệt độ Celsius với validation."""
if value < -273.15:
raise ValueError("Nhiệt độ dưới độ không tuyệt đối!")
self._celsius = value
@property
def fahrenheit(self) -> float:
"""Lấy nhiệt độ theo Fahrenheit (property tính toán)."""
return self._celsius * 9/5 + 32
@fahrenheit.setter
def fahrenheit(self, value: float) -> None:
"""Đặt nhiệt độ bằng Fahrenheit."""
self.celsius = (value - 32) * 5/9 # Dùng celsius setter
# Sử dụng
temp = Temperature(25)
print(f"{temp.celsius}°C = {temp.fahrenheit}°F") # 25.0°C = 77.0°F
temp.celsius = 30
print(f"{temp.celsius}°C = {temp.fahrenheit}°F") # 30.0°C = 86.0°F
temp.fahrenheit = 32
print(f"{temp.celsius}°C") # 0.0°CClass Methods và Static Methods
from datetime import datetime
class Person:
"""Người với năm sinh."""
population = 0 # Biến class
def __init__(self, name: str, birth_year: int) -> None:
self.name = name
self.birth_year = birth_year
Person.population += 1
def get_age(self) -> int:
"""Instance method: cần self."""
return datetime.now().year - self.birth_year
@classmethod
def from_birth_date(cls, name: str, birth_date: str) -> "Person":
"""Class method: constructor thay thế."""
year = int(birth_date.split("-")[0])
return cls(name, year)
@staticmethod
def is_adult(age: int) -> bool:
"""Static method: không cần class hay instance."""
return age >= 18
# Sử dụng
person1 = Person("Alice", 1990)
person2 = Person.from_birth_date("Bob", "1985-05-15") # Class method
print(person1.get_age()) # ví dụ, 36
print(Person.is_adult(person1.get_age())) # True
print(f"Dân số: {Person.population}") # 24. Dataclasses (Python 3.10+)
Dataclasses tự động tạo các phương thức đặc biệt cho classes lưu trữ dữ liệu.
Dataclass Cơ Bản
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class Product:
"""Sản phẩm trong hệ thống kho."""
name: str
price: float
quantity: int = 0
category: Optional[str] = None
def total_value(self) -> float:
"""Tính tổng giá trị kho."""
return self.price * self.quantity
# Tự động có __init__, __repr__, __eq__
product = Product("Laptop", 999.99, 10, "Electronics")
print(product)
# Product(name='Laptop', price=999.99, quantity=10, category='Electronics')
print(product.total_value()) # 9999.90Tính Năng Dataclass Nâng Cao
from dataclasses import dataclass, field
from datetime import datetime
@dataclass(frozen=True) # Dataclass bất biến
class Point:
"""Điểm 2D bất biến."""
x: float
y: float
def distance_from_origin(self) -> float:
return (self.x**2 + self.y**2) ** 0.5
@dataclass
class Order:
"""Đơn hàng với trường được tạo tự động."""
customer_id: str
items: list[Product] = field(default_factory=list) # Default có thể thay đổi
order_date: datetime = field(default_factory=datetime.now)
order_id: str = field(init=False) # Được tạo, không có trong __init__
def __post_init__(self) -> None:
"""Được gọi sau __init__ để đặt trường được tạo."""
self.order_id = f"ORD-{self.customer_id}-{self.order_date.timestamp()}"
def add_item(self, product: Product) -> None:
self.items.append(product)
def total_cost(self) -> float:
return sum(p.price * p.quantity for p in self.items)
# Sử dụng
order = Order("CUST123")
order.add_item(Product("Mouse", 29.99, 2))
order.add_item(Product("Keyboard", 79.99, 1))
print(order.order_id) # ORD-CUST123-1737897600.0
print(f"Tổng: ${order.total_cost():.2f}") # Tổng: $139.975. Comprehensions
Comprehensions cung cấp cách ngắn gọn để tạo lists, dictionaries, và sets.
List Comprehensions
# Cú pháp cơ bản: [biểu_thức for phần_tử in iterable if điều_kiện]
# Không dùng comprehension
squares = []
for x in range(10):
squares.append(x**2)
# Dùng comprehension (sạch hơn)
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# Với lọc
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
# Vòng lặp lồng nhau
pairs = [(x, y) for x in range(3) for y in range(3) if x != y]
print(pairs) # [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
# Biến đổi chuỗi
names = ["alice", "bob", "charlie"]
capitalized = [name.title() for name in names]
print(capitalized) # ['Alice', 'Bob', 'Charlie']Dictionary Comprehensions
# Cú pháp cơ bản: {key_expr: value_expr for item in iterable}
# Tạo mapping từ số sang bình phương
squares_dict = {x: x**2 for x in range(6)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Đổi keys và values
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
# Lọc dictionary
scores = {"Alice": 85, "Bob": 92, "Charlie": 78, "David": 95}
high_scorers = {name: score for name, score in scores.items() if score >= 90}
print(high_scorers) # {'Bob': 92, 'David': 95}Set Comprehensions
# Cú pháp cơ bản: {biểu_thức for phần_tử in iterable}
# Độ dài từ duy nhất
text = "the quick brown fox jumps over the lazy dog"
word_lengths = {len(word) for word in text.split()}
print(word_lengths) # {3, 4, 5}
# Loại bỏ trùng lặp với biến đổi
numbers = [1, -2, 3, -4, 5, -1, 2]
absolute_values = {abs(n) for n in numbers}
print(absolute_values) # {1, 2, 3, 4, 5}Generator Expressions
Generator expressions giống list comprehensions nhưng tạo iterators (lazy evaluation).
# Cú pháp: (biểu_thức for phần_tử in iterable)
# Dùng dấu ngoặc đơn thay vì ngoặc vuông
# List comprehension: tạo list đầy đủ trong bộ nhớ
squares_list = [x**2 for x in range(1000000)] # Dùng ~4MB bộ nhớ
# Generator expression: lazy evaluation
squares_gen = (x**2 for x in range(1000000)) # Dùng ~80 bytes
# Lặp một lần
for sq in squares_gen:
if sq > 100:
print(sq)
break # 121
# Hữu ích cho datasets lớn
def read_large_file(file_path: str):
"""Generator để đọc file từng dòng."""
with open(file_path) as f:
# Xử lý dòng lazily mà không load toàn bộ file
return (line.strip().upper() for line in f if line.strip())
# Dùng trong tham số hàm
total = sum(x**2 for x in range(100)) # Không cần ngoặc thêm
print(total) # 3283506. Decorators Cơ Bản
Decorators là hàm thay đổi hành vi của hàm hoặc class khác.
Function Decorators
from functools import wraps
from time import time, sleep
from typing import Callable, Any
def timer(func: Callable) -> Callable:
"""Decorator để đo thời gian thực thi hàm."""
@wraps(func) # Bảo toàn metadata của hàm gốc
def wrapper(*args: Any, **kwargs: Any) -> Any:
start = time()
result = func(*args, **kwargs)
end = time()
print(f"{func.__name__} mất {end - start:.4f}s")
return result
return wrapper
@timer
def slow_function() -> None:
"""Một hàm chậm."""
sleep(1)
print("Xong!")
slow_function()
# Xong!
# slow_function mất 1.0012sDecorators Với Tham Số
from typing import Callable, Any
def repeat(times: int) -> Callable:
"""Decorator lặp lại thực thi hàm."""
def decorator(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
for _ in range(times):
result = func(*args, **kwargs)
return result # Trả về kết quả cuối
return wrapper
return decorator
@repeat(times=3)
def greet(name: str) -> str:
message = f"Xin chào, {name}!"
print(message)
return message
greet("Alice")
# Xin chào, Alice!
# Xin chào, Alice!
# Xin chào, Alice!Built-in Decorators
class Circle:
"""Hình tròn với tính toán diện tích cached."""
def __init__(self, radius: float) -> None:
self._radius = radius
@property
def radius(self) -> float:
return self._radius
@radius.setter
def radius(self, value: float) -> None:
if value < 0:
raise ValueError("Bán kính không thể âm")
self._radius = value
@staticmethod
def from_diameter(diameter: float) -> "Circle":
"""Tạo hình tròn từ đường kính."""
return Circle(diameter / 2)
@classmethod
def unit_circle(cls) -> "Circle":
"""Tạo hình tròn đơn vị."""
return cls(1.0)
circle = Circle.unit_circle()
print(circle.radius) # 1.0Để tìm hiểu toàn diện về decorators, xem Python Decorators Chuyên Sâu.
7. Context Managers
Context managers xử lý quản lý tài nguyên (setup/teardown) tự động bằng câu lệnh with.
Sử Dụng Built-in Context Managers
# Xử lý file (tự động đóng)
with open("data.txt", "w") as f:
f.write("Xin chào!")
# File tự động đóng ở đây
# Nhiều context managers
with open("input.txt") as infile, open("output.txt", "w") as outfile:
data = infile.read()
outfile.write(data.upper())Tạo Custom Context Managers
from typing import Optional
class DatabaseConnection:
"""Kết nối database với cleanup tự động."""
def __init__(self, host: str, port: int) -> None:
self.host = host
self.port = port
self.connection: Optional[str] = None
def __enter__(self) -> "DatabaseConnection":
"""Setup: được gọi khi vào block 'with'."""
print(f"Đang kết nối tới {self.host}:{self.port}...")
self.connection = f"Connection to {self.host}"
return self
def __exit__(self, exc_type, exc_val, exc_tb) -> bool:
"""Cleanup: được gọi khi thoát block 'with'."""
print(f"Đang đóng kết nối tới {self.host}...")
self.connection = None
# Trả về False để lan truyền exceptions, True để ngăn chặn
return False
def query(self, sql: str) -> str:
"""Thực thi query."""
if not self.connection:
raise RuntimeError("Không có kết nối active")
return f"Kết quả của: {sql}"
# Sử dụng
with DatabaseConnection("localhost", 5432) as db:
result = db.query("SELECT * FROM users")
print(result)
# Kết nối tự động đóng sau block
# Đang kết nối tới localhost:5432...
# Kết quả của: SELECT * FROM users
# Đang đóng kết nối tới localhost...Context Manager Dùng contextlib
from contextlib import contextmanager
from typing import Iterator
@contextmanager
def temporary_setting(config: dict, key: str, value: Any) -> Iterator[None]:
"""Tạm thời thay đổi giá trị config."""
old_value = config.get(key)
config[key] = value
try:
yield # Code trong block 'with' chạy ở đây
finally:
# Khôi phục giá trị gốc
if old_value is None:
config.pop(key, None)
else:
config[key] = old_value
# Sử dụng
config = {"debug": False, "timeout": 30}
print(config) # {'debug': False, 'timeout': 30}
with temporary_setting(config, "debug", True):
print(config) # {'debug': True, 'timeout': 30}
print(config) # {'debug': False, 'timeout': 30} - đã khôi phục8. Type Hints Nền Tảng
Type hints cải thiện khả năng đọc code và cho phép kiểm tra kiểu tĩnh với các công cụ như mypy.
Type Hints Cơ Bản
from typing import List, Dict, Set, Tuple, Optional, Union
# Chú thích hàm
def greet(name: str, age: int) -> str:
"""Chào một người."""
return f"Xin chào {name}, bạn {age} tuổi"
# Chú thích biến
username: str = "alice"
user_id: int = 12345
is_active: bool = True
# Collections (kiểu cũ - Python 3.9+)
from typing import List, Dict
names: List[str] = ["Alice", "Bob", "Charlie"]
scores: Dict[str, int] = {"Alice": 95, "Bob": 87}
# Kiểu hiện đại (Python 3.10+)
names: list[str] = ["Alice", "Bob", "Charlie"]
scores: dict[str, int] = {"Alice": 95, "Bob": 87}
coordinates: tuple[float, float] = (10.5, 20.3)Optional và Union Types
from typing import Optional, Union
# Optional[X] là viết tắt cho Union[X, None]
def find_user(user_id: int) -> Optional[str]:
"""Tìm user theo ID, trả về None nếu không tìm thấy."""
users = {1: "Alice", 2: "Bob"}
return users.get(user_id) # Trả về str hoặc None
# Union cho nhiều kiểu có thể
def process_id(user_id: Union[int, str]) -> str:
"""Xử lý user ID là int hoặc string."""
return str(user_id)
# Python 3.10+ dùng | thay cho Union
def process_id_modern(user_id: int | str) -> str:
"""Cú pháp union hiện đại."""
return str(user_id)Type Hints Cho Classes
from typing import ClassVar
from dataclasses import dataclass
@dataclass
class Employee:
"""Nhân viên với type hints."""
name: str
employee_id: int
salary: float
department: Optional[str] = None
# Class variable (chia sẻ giữa instances)
company_name: ClassVar[str] = "TechCorp"
def give_raise(self, amount: float) -> None:
"""Tăng lương."""
self.salary += amount
def get_info(self) -> dict[str, str | int | float]:
"""Trả về thông tin nhân viên dạng dict."""
return {
"name": self.name,
"id": self.employee_id,
"salary": self.salary,
}Type Aliases
from typing import TypeAlias
# Tạo type aliases cho kiểu phức tạp
UserId: TypeAlias = int
Username: TypeAlias = str
UserData: TypeAlias = dict[str, Union[str, int, bool]]
def create_user(user_id: UserId, username: Username) -> UserData:
"""Tạo dữ liệu user."""
return {
"id": user_id,
"username": username,
"active": True,
}Để tìm hiểu toàn diện về type hints, xem Type Hints & Typing Chuyên Sâu.
9. Ví Dụ Thực Tế: Xây Dựng Task Manager
Hãy kết hợp mọi thứ chúng ta đã học vào một ví dụ thực tế:
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, ClassVar
from enum import Enum
class Priority(Enum):
"""Mức độ ưu tiên task."""
LOW = 1
MEDIUM = 2
HIGH = 3
URGENT = 4
class Status(Enum):
"""Trạng thái task."""
TODO = "todo"
IN_PROGRESS = "in_progress"
DONE = "done"
@dataclass
class Task:
"""Đại diện cho task trong task manager."""
title: str
description: str = ""
priority: Priority = Priority.MEDIUM
status: Status = Status.TODO
created_at: datetime = field(default_factory=datetime.now)
completed_at: Optional[datetime] = None
task_count: ClassVar[int] = 0
def __post_init__(self) -> None:
Task.task_count += 1
def complete(self) -> None:
"""Đánh dấu task hoàn thành."""
self.status = Status.DONE
self.completed_at = datetime.now()
@property
def is_overdue(self) -> bool:
"""Kiểm tra task quá hạn (>7 ngày và chưa xong)."""
if self.status == Status.DONE:
return False
age = (datetime.now() - self.created_at).days
return age > 7
def __str__(self) -> str:
status_icon = "✅" if self.status == Status.DONE else "⏳"
return f"{status_icon} [{self.priority.name}] {self.title}"
class TaskManager:
"""Quản lý tập hợp các tasks."""
def __init__(self) -> None:
self.tasks: list[Task] = []
def add_task(self, task: Task) -> None:
"""Thêm task vào manager."""
self.tasks.append(task)
def get_tasks_by_status(self, status: Status) -> list[Task]:
"""Lấy tất cả tasks với trạng thái cụ thể."""
return [task for task in self.tasks if task.status == status]
def get_high_priority_tasks(self) -> list[Task]:
"""Lấy tasks ưu tiên cao và khẩn cấp."""
return [
task for task in self.tasks
if task.priority in (Priority.HIGH, Priority.URGENT)
and task.status != Status.DONE
]
@property
def completion_rate(self) -> float:
"""Tính tỷ lệ hoàn thành theo phần trăm."""
if not self.tasks:
return 0.0
completed = len([t for t in self.tasks if t.status == Status.DONE])
return (completed / len(self.tasks)) * 100
def __len__(self) -> int:
"""Trả về số lượng tasks."""
return len(self.tasks)
def __str__(self) -> str:
return f"TaskManager({len(self.tasks)} tasks, {self.completion_rate:.1f}% hoàn thành)"
# Sử dụng
manager = TaskManager()
# Thêm tasks
manager.add_task(Task(
"Implement user authentication",
"Thêm chức năng login/logout",
Priority.HIGH
))
manager.add_task(Task(
"Viết tài liệu",
"Tài liệu hóa API endpoints",
Priority.MEDIUM
))
manager.add_task(Task(
"Sửa bug nghiêm trọng",
"Sửa lỗi xử lý thanh toán",
Priority.URGENT
))
# Đánh dấu task đầu tiên hoàn thành
manager.tasks[0].complete()
# Lấy tasks ưu tiên cao
urgent_tasks = manager.get_high_priority_tasks()
for task in urgent_tasks:
print(task)
# ⏳ [URGENT] Sửa bug nghiêm trọng
print(manager) # TaskManager(3 tasks, 33.3% hoàn thành)
print(f"Tổng tasks đã tạo: {Task.task_count}") # 310. Best Practices
✅ Dùng dataclasses cho lưu trữ dữ liệu: Giảm boilerplate code
✅ Ưu tiên composition hơn inheritance: Quan hệ "has-a" thường rõ ràng hơn "is-a"
✅ Dùng type hints: Cải thiện khả năng đọc code và bắt bugs sớm
✅ Giữ comprehensions dễ đọc: Nếu phức tạp, dùng loop thay vì
✅ Dùng properties cho thuộc tính tính toán: Duy trì giao diện sạch
✅ Tuân theo quy ước đặt tên: _private, __name_mangled, public
✅ Dùng context managers cho tài nguyên: Đảm bảo cleanup đúng cách
✅ Viết docstrings: Tài liệu hóa classes và phương thức public
11. Lỗi Thường Gặp
❌ Tham số mặc định có thể thay đổi: Dùng field(default_factory=list) trong dataclasses
❌ Quên self: Tham số đầu tiên của instance methods phải là self
❌ Lạm dụng inheritance: Phân cấp kế thừa sâu khó bảo trì
❌ Comprehensions phức tạp: Chia thành nhiều dòng hoặc dùng loops cho rõ ràng
❌ Không dùng @wraps: Luôn dùng functools.wraps trong decorators
❌ Sửa đổi lists trong khi lặp: Tạo bản sao trước hoặc dùng list comprehension
# ❌ TỆ: Tham số mặc định có thể thay đổi
def add_item(item: str, items: list = []) -> list:
items.append(item)
return items
# ✅ TỐT: Dùng None và tạo list mới
def add_item(item: str, items: Optional[list] = None) -> list:
if items is None:
items = []
items.append(item)
return items
# ❌ TỆ: Sửa đổi list trong khi lặp
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # Bỏ qua phần tử!
# ✅ TỐT: Dùng list comprehension
numbers = [1, 2, 3, 4, 5]
numbers = [num for num in numbers if num % 2 != 0]Tóm Tắt và Điểm Chính
Trong giai đoạn này, bạn đã học:
✅ Classes và OOP: Tạo code có thể tái sử dụng, có tổ chức với classes và kế thừa
✅ Phương thức đặc biệt: Tùy chỉnh hành vi object với magic methods
✅ Properties: Kiểm soát truy cập thuộc tính với @property decorator
✅ Dataclasses: Đơn giản hóa classes lưu trữ dữ liệu với phương thức tự động
✅ Comprehensions: Viết biến đổi ngắn gọn, dễ đọc cho lists, dicts, và sets
✅ Generators: Xử lý datasets lớn hiệu quả với lazy evaluation
✅ Decorators: Sửa đổi hành vi hàm một cách sạch và có thể tái sử dụng
✅ Context managers: Quản lý tài nguyên an toàn với câu lệnh with
✅ Type hints: Cải thiện chất lượng code với static typing
Bài Tập Thực Hành
- Xây Dựng Hệ Thống Thư Viện: Tạo classes cho
Book,Member, vàLibraryvới chức năng mượn/trả - Implement Decorator: Viết decorator
@cachememoizes kết quả hàm - Pipeline Xử Lý Dữ Liệu: Dùng comprehensions và generators để xử lý dataset lớn hiệu quả
Bước Tiếp Theo
Tiếp tục với Giai Đoạn 3: Thư Viện Chuẩn & Công Cụ để học về thư viện chuẩn mạnh mẽ của Python và các công cụ phát triển chuyên nghiệp.
Trước đó: Giai Đoạn 1: Nền Tảng Python
Các Bài Chuyên Sâu Liên Quan:
- Python Decorators - Hướng dẫn toàn diện về decorators
- Type Hints & Typing - Thành thạo hệ thống type của Python
Thuộc chuỗi bài Lộ Trình Học Python
📬 Đăng ký nhận bản tin
Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.
Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.
💬 Comments
Đăng nhập để bình luận
Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.