Lập trình hướng đối tượng (OOP) trong Python 3 là một phương pháp tổ chức mã nguồn dựa trên các đối tượng và lớp, giúp quản lý độ phức tạp của phần mềm hiệu quả hơn. Phương pháp này dựa trên bốn trụ cột chính: tính đóng gói, tính kế thừa, tính đa hình và tính trừu tượng. Bài viết này sẽ đi sâu vào cú pháp, cơ chế hoạt động và các kỹ thuật thực tiễn khi làm việc với OOP trong Python.
1. Nguyên Lý Cốt Lõi
- Lớp (Class): Đóng vai trò là bản thiết kế, quy định các thuộc tính và phương thức mà đối tượng sẽ có.
- Đối tượng (Object): Là thực thể cụ thể được tạo ra từ lớp, mang trạng thái và hành vi riêng biệt.
- Các nguyên tắc chính:
- Đóng gói: Giấu dữ liệu nội bộ và chỉ cho phép truy cập qua giao thức định sẵn.
- Kế thừa: Cho phép lớp con tái sử dụng và mở rộng chức năng từ lớp cha.
- Đa hình: Cùng một giao diện nhưng nhiều cách thực hiện khác nhau tùy đối tượng.
- Trừu tượng: Tập trung vào những gì đối tượng làm thay vì cách nó thực hiện.
2. Khai Báo Lớp Và Khởi Tạo Đối Tượng
Để định nghĩa một lớp, chúng ta sử dụng từ khóa class. Phương thức __init__ đóng vai trò là hàm khởi tạo, tự động gọi khi tạo实例 mới.
class Product:
def __init__(self, title, price):
self.title = title # Thuộc tính đối tượng
self.price = price
def get_info(self):
return f"{self.title}: ${self.price}"
# Khởi tạo đối tượng
item = Product("Laptop", 999)
print(item.title) # Truy cập thuộc tính
print(item.get_info()) # Gọi phương thức
Tham số self luôn là tham số đầu tiên trong các phương thức của lớp, đại diện cho chính đối tượng đang được thao tác.
3. Quản Lý Thuộc Tính
Thuộc tính đối tượng (Instance Attributes)
Dữ liệu riêng biệt cho từng实例, thường được gán trong __init__.
class Employee:
def __init__(self, emp_id):
self.emp_id = emp_id
worker = Employee(101)
Thuộc tính lớp (Class Attributes)
Dữ liệu chia sẻ chung cho tất cả các实例 của lớp đó.
class Employee:
company = "TechCorp" # Thuộc tính lớp
def __init__(self, emp_id):
self.emp_id = emp_id
print(Employee.company) # Truy cập qua lớp
print(worker.company) # Truy cập qua đối tượng
Thuộc tính động
Python cho phép thêm thuộc tính mới vào đối tượng trong quá trình chạy, tuy nhiên cần thận trọng để tránh lỗi logic.
worker.level = "Senior"
print(worker.level)
4. Phân Loại Phương Thức
Phương thức đối tượng
Truy cập và thay đổi trạng thái của đối tượng thông qua self.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def calculate_area(self):
return self.width * self.height
Phương thức lớp
Sử dụng trang trí @classmethod, nhận cls làm tham số đầu tiên. Thường dùng cho các factory method.
class Order:
total_orders = 0
def __init__(self, order_id):
self.order_id = order_id
Order.total_orders += 1
@classmethod
def get_count(cls):
return cls.total_orders
Phương thức tĩnh
Sử dụng @staticmethod, không nhận self hay cls. Dùng cho các hàm tiện ích không phụ thuộc trạng thái lớp.
class MathHelper:
@staticmethod
def multiply(x, y):
return x * y
print(MathHelper.multiply(5, 3))
5. Kỹ Thuật Đóng Gói
Thuộc tính riêng tư
Sử dụng hai dấu gạch dưới __ để kích hoạt cơ chế name mangling, hạn chế truy cập trực tiếp từ bên ngoài.
class Wallet:
def __init__(self, fund):
self.__fund = fund # Riêng tư
def withdraw(self, amount):
if amount <= self.__fund:
self.__fund -= amount
return True
return False
def check_balance(self):
return self.__fund
my_wallet = Wallet(1000)
# print(my_wallet.__fund) # Sẽ báo lỗi
print(my_wallet.check_balance())
Thuộc tính bảo vệ
Một dấu gạch dưới _ là quy ước cho biết thuộc tính này chỉ nên dùng nội bộ, nhưng không bị chặn kỹ thuật.
Sử dụng Property
Decorator @property cho phép kiểm soát việc đọc và ghi thuộc tính như một phương thức.
class User:
def __init__(self, username):
self._username = username
@property
def username(self):
return self._username
@username.setter
def username(self, value):
if len(value) < 3:
raise ValueError("Username too short")
self._username = value
account = User("john")
account.username = "john_doe" # Hợp lệ
6. Cơ Chế Kế Thừa
Lớp con có thể kế thừa toàn bộ thuộc tính và phương thức của lớp cha.
class Vehicle:
def __init__(self, brand):
self.brand = brand
def move(self):
return "Moving..."
class Car(Vehicle):
def move(self):
return f"{self.brand} is driving on road"
my_car = Car("Toyota")
print(my_car.move())
Gọi phương thức cha
Hàm super() giúp gọi lại phương thức khởi tạo hoặc phương thức của lớp cha.
class Truck(Vehicle):
def __init__(self, brand, capacity):
super().__init__(brand)
self.capacity = capacity
Đa kế thừa
Python hỗ trợ kế thừa từ nhiều lớp cùng lúc. Thứ tự tìm kiếm phương thức tuân theo MRO (Method Resolution Order).
class A:
def process(self): return "A"
class B:
def process(self): return "B"
class C(A, B):
pass
obj = C()
print(obj.process()) # Kết quả là "A" theo thứ tự MRO
7. Tính Đa Hình
Cho phép các đối tượng khác nhau phản hồi cùng một lời gọi phương thức theo cách riêng.
def start_engine(vehicle):
print(vehicle.move())
start_engine(Car("Honda"))
start_engine(Truck("Ford", 100))
Duck Typing
Python không kiểm tra kiểu đối tượng chặt chẽ. Nếu đối tượng có phương thức cần thiết, nó sẽ hoạt động.
class Boat:
def move(self):
return "Sailing..."
start_engine(Boat()) # Hoạt động bình thường dù không kế thừa Vehicle
8. Phương Thức Đặc Biệt (Magic Methods)
Các phương thức bắt đầu và kết thúc bằng hai dấu gạch dưới cho phép tùy biến hành vi của đối tượng với các toán tử.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Vector({self.x}, {self.y})"
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(v1 == Vector(1, 2)) # True
9. Các Tính Năng Nâng Cao
Lớp Trừu Tượng (ABC)
Module abc giúp định nghĩa các lớp cơ sở không thể khởi tạo trực tiếp, buộc lớp con phải cài đặt phương thức cụ thể.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
Metaclass
Siêu lớp định nghĩa cách một lớp được tạo ra, thường dùng trong các framework phức tạp để đăng ký lớp tự động.
class RegisterMeta(type):
def __new__(cls, name, bases, attrs):
attrs['registered'] = True
return super().__new__(cls, name, bases, attrs)
class Plugin(metaclass=RegisterMeta):
pass
print(Plugin.registered) # True
10. Nguyên Tắc Thiết Kế Tốt
- Trách nhiệm đơn lẻ: Mỗi lớp chỉ nên giải quyết một vấn đề cụ thể.
- Ưu tiên组合 (Composition): Thay vì kế thừa sâu, hãy sử dụng đối tượng này bên trong đối tượng khác.
class Engine:
def ignite(self):
return "Ignited"
class Vehicle:
def __init__(self):
self.engine = Engine() # Composition
def start(self):
return self.engine.ignite()
- Đặt tên rõ ràng: Lớp dùng
CamelCase, hàm và thuộc tính dùngsnake_case. - Docstrings: Luôn viết tài liệu mô tả cho lớp và phương thức public.
11. Ứng Dụng Thực Tế
Mô hình hóa dữ liệu
class Customer:
def __init__(self, name, email):
self.name = name
self.email = email
def update_email(self, new_email):
self.email = new_email
Xây dựng API Client
import requests
class ApiClient:
def __init__(self, base_url):
self.base_url = base_url
def fetch(self, endpoint):
url = f"{self.base_url}/{endpoint}"
response = requests.get(url)
return response.json()
Phát triển Game
class Character:
def __init__(self, hp):
self.hp = hp
def attack(self, target):
target.hp -= 10