Lập Trình Hướng Đối Tượng Cơ Bản Và Nâng Cao Trong Python 3

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ùng snake_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

Thẻ: python oop class inheritance encapsulation

Đăng vào ngày 8 tháng 6 lúc 01:36